72 中序遍历和后序遍历树构造二叉树
描述
根据中序遍历和后序遍历树构造二叉树
你可以假设树中不存在相同数值的节点
您在真实的面试中是否遇到过这个题?
样例
给出树的中序遍历: [1,2,3] 和后序遍历: [1,3,2]
返回如下的树:
2
/ \
1 3
标签
二叉树
思路:要建立二叉树,首先要建立根节点,其次才是建立左右孩子并挂载。PS:建立链表是先确定前驱节点,再挂载。
1.已知中序遍历和后序遍历,如何确定根节点?我们知道,后序遍历是左右根,所以后序遍历的最后一个节点是当前树的根节点。
2.接下来是左右孩子,要借助中序遍历。中序遍历里,根节点左侧是左子树,右侧是右子树。先定位根节点(前提是树中不存在相同数值的节点),则左右子树的数量就可以确定了。根据左右子树的数量可以确定左右子树的中序遍历和后序遍历,递归构建并挂载左右子树即可。
3.当中序遍历的起始索引大于结束索引时,说明二叉树已经建立完毕。
AC代码:
/**
* Definition of TreeNode:
* class TreeNode {
* public:
* int val;
* TreeNode *left, *right;
* TreeNode(int val) {
* this->val = val;
* this->left = this->right = NULL;
* }
* }
*/
class Solution {
public:
/**
* @param inorder: A list of integers that inorder traversal of a tree
* @param postorder: A list of integers that postorder traversal of a tree
* @return: Root of a tree
*/
TreeNode * buildTree(vector<int> &inorder, vector<int> &postorder) {
// write your code here
int a=inorder.size();
int b=postorder.size();
if (a!=b||a==0||b==0)
{
return NULL;
}
return Build(inorder,postorder,0,a-1,0,b-1);
}
TreeNode * Build(vector<int> &inorder, vector<int> &postorder,int inst,int ined,int post,int poed)
{
if (inst>ined)
{
return NULL;
}
int i=inst;
while(i<=ined&&inorder[i]!=postorder[poed])//找到中序遍历根节点所在位置;
{
i++;
}
TreeNode * root=new TreeNode(postorder[poed]);//根节点;
root->left=Build(inorder,postorder,inst,i-1,post,post+i-1-inst);//左孩子;
root->right=Build(inorder,postorder,i+1,ined,post+i-inst,poed-1);//右孩子;
return root;
}
};
其他方法:
以上两个链接是在中序遍历中定位根节点后,分别创建左子树的中序遍历、后序遍历数组,右子树的中序遍历、后序遍历数组,再递归。
LintCode2016年8月8日算法比赛----中序遍历和后序遍历构造二叉树
PS:最开始的递归函数只设置了起始和终止两个索引,因为我只注意到了左右子树在中序遍历和后序遍历中长度相等,但没注意到左右子树的起始、终止索引在中序遍历与后序遍历中是不一样的ORZ……也不知道当时怎么想的,明明画了图对照……
Mark一下曾经的失败代码:
TreeNode * build(vector<int> &inorder, vector<int> &postorder,int st,int ed)
{
if (st>ed)
{
return NULL;
}
int i=st;
while(i<=ed&&inorder[i]!=postorder[ed])//找到中序遍历根节点所在位置;
{
i++;
}
TreeNode * root=new TreeNode(postorder[ed]);//根节点;
root->left=build(inorder,postorder,st,i-1);//左孩子;
root->right=build(inorder,postorder,i,ed-1);//右孩子,注意是从i开始,不是i+1;
return root;
}
由于右孩子中序、后序区间索引没有一一对应,在编译器上运行【1,2,3】【1,3,2】时栈溢出。程序一直在递归build(inorder,postorder,1,1)……吐血。