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