问题描述
给定两个整数数组
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
保证 为二叉树的中序遍历序列
问题分析:
根据先序序列的首位元素,结合中序序列对左右子树进行划分,并划分先序序列。然后递归构建树。如何划分是这个问题的难点。代码跟大多人的写法基本一样,你要问我为什么发原创,可能原因是因为这代码是我自己手打的。。。
代码如下:
class Solution {
public:
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
if(preorder.size() == 0 || inorder.size() == 0) return nullptr;
return traversal(preorder, inorder);
}
TreeNode* traversal(vector<int>& preorder, vector<int>& inorder){
if(preorder.size() == 0) return nullptr;
int rootvalue = preorder[0];
TreeNode* root = new TreeNode(rootvalue);
if(preorder.size() == 1) return root;
// 找到中序切割点
int segmentindex;
for(segmentindex = 0; segmentindex < inorder.size(); ++segmentindex){
if(inorder[segmentindex] == rootvalue) break;
}
// 切割中序
vector<int> leftinorder(inorder.begin(), inorder.begin() + segmentindex);
vector<int> rightinorder(inorder.begin() + segmentindex + 1, inorder.end());
// 切割先序
vector<int> leftpreorder(preorder.begin() + 1, preorder.begin() + leftinorder.size() + 1);
vector<int> rightpreorder(preorder.begin() + leftinorder.size() + 1, preorder.end());
root->left = traversal(leftpreorder, leftinorder);
root->right = traversal(rightpreorder, rightinorder);
return root;
}
};