72 中序遍历和后序遍历树构造二叉树

原题网址:https://www.lintcode.com/problem/construct-binary-tree-from-inorder-and-postorder-traversal/description

描述

根据中序遍历和后序遍历树构造二叉树

你可以假设树中不存在相同数值的节点

您在真实的面试中是否遇到过这个题?  

样例

给出树的中序遍历: [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;
}
};

 

其他方法:

LintCode-72.中序遍历和后序遍历树构造二叉树

Lintcode---中序遍历和后序遍历树构造二叉树

以上两个链接是在中序遍历中定位根节点后,分别创建左子树的中序遍历、后序遍历数组,右子树的中序遍历、后序遍历数组,再递归。

 

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)……吐血。

 

 

 

posted @ 2018-07-05 23:41  eeeeeeee鹅  阅读(644)  评论(0编辑  收藏  举报