《从头再来》剑指offer.07 重建二叉树
输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
思路:根据前序遍历找到根结点,然后从中序遍历中找到根结点,则根结点的左边为左子树的值,根结点的右边为右子树的值。然后递归的重建即可。
/** * 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* ReBuildTree(vector<int>& preorder, vector<int>& inorder, int prel, int prer, int inl, int inr){ //首先定义递归的返回条件 if(prel > prer) return nullptr;//如果超过范围,返回空 //利用前序遍历的第一个值,重建根结点,一定是前序遍历的第一位的值preorder[prel]; TreeNode* root = new TreeNode(preorder[prel]); //然后利用中序遍历来确定左右子树的范围 int count = 0; //i应该成中序遍历的左边开始,也就是inl,而不是0;同时可以取到最右边,所以判断条件为小于等于 for(int i = inl; i <= inr; ++i){ if(root->val == inorder[i]) break; count++; } //取得左右子树的范围后,就可以重建了 root->left = ReBuildTree(preorder, inorder, prel+1, prel+count,inl, inl+count-1); root->right = ReBuildTree(preorder, inorder, prel+count+1, prer, inl+count+1,inr); //重建完成,返回根结点 return root; } TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) { int end = preorder.size() - 1;//大小一定是size()-1 return ReBuildTree(preorder, inorder, 0, end, 0, end);//调用函数后,一定要返回!!! } };
解题的过程中遇到了如下几个问题:
1、重建函数的函数类型?按照题意应该是TreeNode* ,所以讲道理,二叉树的函数类型,应该都是TreeNode*
2、递归的返回条件?返回什么? 当前序遍历的左边范围超过了右边范围的时候,就该返回了。当然是返回nullptr/NULL
3、重建根结点的时候,值是啥? 值一定是preorder[prel],也就是前序遍历的第一个值,而不是prel!!!
4、进行左右子树范围界定的时候,i的值是从inl也就是中序遍历的第一位开始,到中序遍历的最后一位结束(i <= inr),而不是从0开始
5、主函数调用重建函数时,前面一定要加return!因为重建函数会return整个树,必须有东西来接收这个树。或者还有一种解决方法,新建一个TreeNode* result来接收重建函数的值,然后返回新建的result。
最后,还有最需要注意的点,就是重建时的范围划分。如有必要,则一定在纸上分析清楚。
《从头再来》

浙公网安备 33010602011771号