LeetCode原题
105. 从前序与中序遍历序列构造二叉树
给定两个整数数组 preorder 和 inorder ,其中 preorder 是二叉树的先序遍历, inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点。
示例 1:
输入: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
输出: [3,9,20,null,null,15,7]
示例 2:
输入: preorder = [-1], inorder = [-1]
输出: [-1]
提示:
1 <= preorder.length <= 3000
inorder.length == preorder.length
-3000 <= preorder[i], inorder[i] <= 3000
preorder 和 inorder 均 无重复 元素
inorder 均出现在 preorder
preorder 保证 为二叉树的前序遍历序列
inorder 保证 为二叉树的中序遍历序列
解题思路
这题是一道中等题,但是只要抓住前序遍历和中序遍历两者的特性,想要做出这道题还是很简单的。
1、已知前序遍历,便可以找到该二叉树的头节点;
2、已知中序遍历,有知道了头节点,便可以通过头节点把中序遍历的左、右子树切割出来
3、通过从中序遍历中切割出来的左右子树,以及头节点的位置,我们可以通过
头节点的位置 - 左子树最左边的位置 = 左子树的长度
(这里你也可以求右子树的)
4、得到了左子树的长度后,便可以在前序遍历中的出左子树范围;
5、前序遍历中左子树的范围出来了,根据前序遍历的特性,又可以得出左子树的头节点,然后的便可以把这个子树当作一个 单独的树,不断重复上面的动作,得出最终的答案
C++代码
class Solution {
public:
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
return helper(preorder,0,preorder.size()-1,inorder,0,inorder.size()-1);
}
TreeNode* helper(vector<int>& preorder,int l1,int r1,vector<int>& inorder,int l2,int r2){
if(l1>r1) return NULL; //因为节点数都一样,只要其中一个的长度不符合要求,都返回空
TreeNode* root=new TreeNode;
root->val=preorder[l1]; //每一个前序遍历的第一个都是头节点
int p=0;
while(inorder[p]!=root->val) p++; //找到头节点的位置
int llen=p-l2; //左子树的长度
//切割成左右子树,然后不断的递归调用
root->left=helper(preorder,l1+1,l1+llen,inorder,l2,p-1);
root->right=helper(preorder,l1+llen+1,r1,inorder,p+1,r2);
return root;
}
};