面试题 17.12. BiNode
二叉树数据结构TreeNode可用来表示单向链表(其中left置空,right为下一个链表节点)。实现一个方法,把二叉搜索树转换为单向链表,要求依然符合二叉搜索树的性质,转换操作应是原址的,也就是在原始的二叉搜索树上直接修改。
返回转换后的单向链表的头节点。
示例:
输入: [4,2,5,1,3,null,6,0]
输出: [0,null,1,null,2,null,3,null,4,null,5,null,6]
提示:
节点数量不会超过 100000
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */
代码一:(未实现原地转换)
class Solution { public: TreeNode* convertBiNode(TreeNode* root) { //思路:二叉排序树层序遍历转中序遍历 TreeNode* root1=new TreeNode; vector<int> vec; inorder(root,vec); int n=vec.size(); root1=Create(n,vec); return root1; } void inorder(TreeNode* root,vector<int> &vec){ if(root==NULL) return; inorder(root->left,vec); vec.push_back(root->val); inorder(root->right,vec); } TreeNode* Create(int n,vector<int> vec) { TreeNode* root=NULL; for(int i=0;i<n;i++) { insert(root,vec[i]); } return root; } void insert(TreeNode* &root,int x) { if(root==NULL) { root=newNode(x); return; } insert(root->right,x); } TreeNode* newNode(int x) { TreeNode* Node=new TreeNode; Node->val=x; Node->left=Node->right=NULL; return Node; } };
代码二:(借鉴所得)
解题思路:
要求是原址修改,即要直接利用这些已经存在的节点空间,修改这些节点的指向来得到单向链表。
要求单向链表依然符合二叉搜索树的性质,说是单向链表,其实还是一棵特殊的二叉搜索树。
众所周知,对二叉搜索树采用中序遍历就能得到一个升序序列。 那么如果我们在遍历过程中,修改每一个根节点的左右指向,不就实现了原址修改了吗。
class Solution { TreeNode* prev=NULL; TreeNode* head=new TreeNode; public: TreeNode* convertBiNode(TreeNode* root) { inOrder(root); return head->right; } void inOrder(TreeNode* root) { if(root==NULL) return; inOrder(root->left); if(prev==NULL) { prev=root; head->right=root; }else{ prev->right=root; prev=root; } root->left=NULL; //!!!别少了 inOrder(root->right); } };
257. 二叉树的所有路径
给定一个二叉树,返回所有从根节点到叶子节点的路径。
说明: 叶子节点是指没有子节点的节点。
示例:
输入:
1
/
2 3
5
输出: ["1->2->5", "1->3"]
解释: 所有根节点到叶子节点的路径为: 1->2->5, 1->3
解题思路:深度优先搜索
最直观的方法是使用深度优先搜索。在深度优先搜索遍历二叉树时,我们需要考虑当前的节点以及它的孩子节点。
如果当前节点不是叶子节点,则在当前的路径末尾添加该节点,并继续递归遍历该节点的每一个孩子节点。
如果当前节点是叶子节点,则在当前路径末尾添加该节点后我们就得到了一条从根节点到叶子节点的路径,将该路径加入到答案即可。
如此,当遍历完整棵二叉树以后我们就得到了所有从根节点到叶子节点的路径。
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode() : val(0), left(nullptr), right(nullptr) {} * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} * }; */
class Solution { public: vector<string> binaryTreePaths(TreeNode* root) { vector<string> vec; DFS(root,"",vec); return vec; } void DFS(TreeNode* root,string str,vector<string> &vec) { if(root==NULL) return; str+=to_string(root->val); if(root->left==NULL&&root->right==NULL) { vec.push_back(str); return; } str+="->"; DFS(root->left,str,vec); DFS(root->right,str,vec); } };
1022. 从根到叶的二进制数之和
给出一棵二叉树,其上每个结点的值都是 0 或 1 。每一条从根到叶的路径都代表一个从最高有效位开始的二进制数。例如,如果路径为 0 -> 1 -> 1 -> 0 -> 1,那么它表示二进制数 01101,也就是 13 。
对树上的每一片叶子,我们都要找出从根到该叶子的路径所表示的数字。
返回这些数字之和。题目数据保证答案是一个 32 位 整数。
示例 1:
输入:root = [1,0,1,0,1,0,1]
输出:22
解释:(100) + (101) + (110) + (111) = 4 + 5 + 6 + 7 = 22
示例 2:
输入:root = [0]
输出:0
示例 3:
输入:root = [1]
输出:1
示例 4:
输入:root = [1,1]
输出:3
提示:
树中的结点数介于 1 和 1000 之间。
Node.val 为 0 或 1 。
解题思路:
当我们知道如何构造一条路径后,剩下的问题就是怎么把二进制转换为十进制。
class Solution { int sum=0; public: int sumRootToLeaf(TreeNode* root) { DFS(root,0); return sum; } void DFS(TreeNode* root,int cur) { if(root==NULL) return; if(root->left==NULL&&root->right==NULL) //深搜遍历到树叶结点 { sum+=(cur*2+root->val); return; } DFS(root->left,cur*2+root->val); DFS(root->right,cur*2+root->val); } };