题目
输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
例如,给出
前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]
返回如下的二叉树:
3
/ \
9 20
/ \
15 7
限制:
0 <= 节点个数 <= 5000
题解
笔记:
递归思想,最重要的是找到前序遍历和中序遍历中的左子树和右子树的起始下标和终止下标(左子树为s1,e1,右子树为s2,e2)
1.判断s1,e1,s2,e2是否越界
1.1 先根据前序遍历找到root的下标,其实就是第一个preorder[s1];
1.2 根据root的val找到根节点在中序遍历的下标i
1.3 那么在下一次的递归中,传入的新参数,易求的有:
root->left左子树的前序遍历下标(s1+1,?),中序遍历下标(s2,i-1)
root->right右子树的前序遍历下标(?+1,e1),中序遍历下标(i+1,e2)
1.4那么仅需要把“?”求出来,“?”是什么呢,其实就是s1+左子树的节点个数=左子树结束节点的位置下标
事实上节点个数在中序遍历中可求得,(i-1)-s2+1=i-s2;那么在前序遍历中,左子树和右子树刚好分开处 的 左子树结束节点的位置即为s1+i-s2="?",所以右子树前序遍历下标即为((s1+i-s2)+1,e1).
代码:
/**
* 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* construct(vector<int>& preorder, vector<int>& inorder,int s1,int e1,int s2,int e2){
if(s1<=e1&&s2<=e2){
int rootval = preorder[s1];
TreeNode* tree = new TreeNode(rootval);
for(int i=s2;i<=e2;i++)
{
if(rootval==inorder[i]){
tree->left = construct(preorder,inorder,s1+1,s1+i-s2,s2,i-1);
tree->right = construct(preorder,inorder,s1+i-s2+1,e1,i+1,e2);
}
}
return tree;
}
return nullptr;
}
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
return construct(preorder,inorder,0,preorder.size()-1,0,inorder.size()-1);
}
};