从前序与中序遍历序列构造二叉树
题目:
根据一棵树的前序遍历与中序遍历构造二叉树。
注意:
你可以假设树中没有重复的元素。
例如,给出
前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]
返回如下的二叉树:
3
/ \
9 20
/ \
15 7
思路:
这两个表格是前序和中序的遍历数组,我们定义
preorder
在闭区间[preStart,preEnd]内,
inorder在闭区间[inStart,inEnd]内
。
第一步:先找到根节点,由先序遍历可知根节点是前序遍历数组中的第一个元素,在上图中标出,记根节点值rootVal 为
preorder
[
preStart
]
第二步,找到根节点值在中序遍历数组中的位置,记为index,使
inorder[index] == rootVal,如下图所示
第三步:可以找到左子树在数组中的长度,如下图所示:
由上述可知:9为根节点的左子树,20,15,7节点为根节点的右子树的节点,这是需要找到右子树的根节点,然后去找到右子树的左子树和右子树的右子树来构造根节点下的右子树。
于是我们在15,20,7中重复上述的一二三步,如下图所示:
所以我们根据上述的分析步骤去递归实现代码,如下所示。
代码:
class Solution {
public:
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
return buildHelp(preorder,0,preorder.size()-1,inorder,0,inorder.size()-1);
}
TreeNode *buildHelp(vector<int>& preorder,int preStart,int preEnd, vector<int>& inorder,int inStart,int inEnd)
{
if (preStart > preEnd)
{
return nullptr;
}
int rootVal = preorder[preStart];
int index = 0;
for (int i = inStart; i <= inEnd; i++)
{
if(inorder[i] == rootVal)
{
index = i;
break;
}
}
int leftSize = index - inStart;
TreeNode* root = new TreeNode(rootVal);
root->left = buildHelp(preorder, preStart + 1, preStart + leftSize,inorder, inStart, index - 1);
root->right = buildHelp(preorder, preStart + leftSize + 1, preEnd,inorder, index + 1, inEnd);
return root;
}
};