106.从中序与后序遍历序列构造二叉树
链接
给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。
示例 1:
输入:inorder = [9,3,15,20,7], postorder = [9,15,7,20,3]
输出:[3,9,20,null,null,15,7]
示例 2:
输入:inorder = [-1], postorder = [-1]
输出:[-1]
思路
- 后序最后一个是root
if(postorder.size()==0) return NULL;
int rootValue= postorder[postorder.size()-1];
TreeNode* root=new TreeNode(rootValue);
- 中序root左边为根的左子树,右边为根的右子树
int delimiterIndex;
for(delimiterIndex=0;delimiterIndex<inorder.size();delimiterIndex++)
{
if(inorder[delimiterIndex]==rootValue) break;
}
vector<int> leftInorder(inorder.begin(),inorder.begin()+delimiterIndex);
vector<int> rightInorder(inorder.begin()+delimiterIndex+1,inorder.end());
- 同一个二叉树,后序的根左子树节点数和中序一样,中序前n个为左子树,后序前n个也为左子树。后序去掉root根节点,剩下的是右子树
vector<int> leftPostorder(postorder.begin(),postorder.begin()+leftInorder.size());
vector<int> rightPostorder(postorder.begin()+leftInorder.size(),postorder.end());
- 中序=左子树+根+右子树
后序=左子树+右子树+根
两个左子树描述的是一个二叉树,只是一个中序一个后序,就和题目一样了,递归
root->left=travel(leftInorder,leftPostorder);
root->right=travel(rightInorder,rightPostorder);
总代码
class Solution {
public:
TreeNode* travel(vector<int>& inorder,vector<int>& postorder)
{
if(postorder.size()==0) return NULL;
int rootValue= postorder[postorder.size()-1];
TreeNode* root=new TreeNode(rootValue);
if(postorder.size()==1) return root;
int delimiterIndex;
for(delimiterIndex=0;delimiterIndex<inorder.size();delimiterIndex++)
{
if(inorder[delimiterIndex]==rootValue) break;
}
vector<int> leftInorder(inorder.begin(),inorder.begin()+delimiterIndex);
vector<int> rightInorder(inorder.begin()+delimiterIndex+1,inorder.end());
postorder.pop_back();
vector<int> leftPostorder(postorder.begin(),postorder.begin()+leftInorder.size());
vector<int> rightPostorder(postorder.begin()+leftInorder.size(),postorder.end());
root->left=travel(leftInorder,leftPostorder);
root->right=travel(rightInorder,rightPostorder);
return root;
}
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
if(inorder.size()==0 && postorder.size()==0) return NULL;
return travel(inorder,postorder);
}
};
出现的问题
在划分左子树,右子树出现了问题
int delimiterIndex;//根节点的位置
for(delimiterIndex=0;delimiterIndex<inorder.size();delimiterIndex++)
{
if(inorder[delimiterIndex]==rootValue) break;
}
vector<int> leftInorder(inorder.begin(),inorder.begin()+delimiterIndex);
vector<int> rightInorder(inorder.begin()+delimiterIndex+1,inorder.end());
postorder.pop_back();//去根节点
vector<int> leftPostorder(postorder.begin(),postorder.begin()+leftInorder.size());
vector<int> rightPostorder(postorder.begin()+leftInorder.size(),postorder.end());
delimiterIndex是从0开始的,
inorder = [9,3,15,20,7],根为3,delimiterIndex=1
ector leftInorder(inorder.begin(),inorder.begin()+delimiterIndex);:
inorder.begin(),指的是第一个元素9
inorder.begin()+delimiterIndex:指的是3,第二个参数为end(),为最后一个元素的下一个元素
leftInorder=[9]
vector rightInorder(inorder.begin()+delimiterIndex+1,inorder.end());
+1是要跳过根节点3
划分是左闭右开区间