105. 从前序与中序遍历序列构造二叉树 - 力扣(LeetCode)
题目要求:
给定两个整数数组 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 递归 O(N^2)
题目说preorder序列(简称p)是前序遍历,inorder(简称i)是中序遍历,那么先从 p 中找到第一个元素,然后找到这个元素在 i 中的位置。
在i中以这个位置为界限,根据中序遍历左根右的顺序,这个位置左边的数组构成它的左子树,右边构成它的右子树。
然后在p中找第二个元素,根据前序遍历根左右的顺序,这个元素一定是左子树的根,然后继续在i中找到它,它的左(不低于0,小于上个根)右(不大于结尾,大于上个根)边,也是它的左右子树。
重复上述过程,直到数组只剩一个节点,它就是某个根的子树,至此就可以从简单到复杂构建子树了。
class Solution {
TreeNode* _buildTree(vector<int>& preorder, vector<int>& inorder, int start,
int end,int left) {
if (start == end)
return new TreeNode(inorder[start]);
for (int i = left; i < preorder.size(); i++) {
for (int j = start; j <= end; j++)
if (preorder[i] == inorder[j]) {
TreeNode*leftTree = _buildTree(preorder,inorder,start,j-1,left+1);
TreeNode*rightTree = _buildTree(preorder,inorder,j+1,end,left+1);
TreeNode* root = new TreeNode(inorder[j],leftTree,rightTree);
return root;
}
}
return nullptr;
}
public:
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder)
{
return _buildTree(preorder,inorder,0,inorder.size()-1,0);
}
};