剑指Offer:重建二叉树

题目描述

输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。

思路:根据二叉树的定义。

前序遍历:1.遍历root根节点

                  2.前序遍历左子树

                  3.前序遍历右子树

 根据前序遍历的结果可知第一个访问的必定是root结点。

中序遍历:1.中序遍历左子树

                  2.遍历root根节点

                  3.中序遍历右子树

根据中序遍历的结果,再结合前序遍历的root结点去划分root结点的左右子树。

后序遍历:1.后序遍历左子树

                  2.后序遍历右子树

                  3.遍历root根节点

根据后序遍历的结果可知最后访问的必定是root结点。

示例:

假如有如下的二叉树:

二叉树
二叉树图

根据上面的定义,得出如下的遍历结果

前序遍历:ABDHIEJCFKG

中序遍历:HDIBEJAFKCG

后序遍历:HIDJEBKFGCA

由此可知根据前序遍历和中序遍历的结果则可重建二叉树

function TreeNode(x) {
    this.val = x;//当前节点的数据域
    this.left = null;//指针左移
    this.right = null;//指针右移
} 
function reConstructBinaryTree(pre, vin)
{
    var root=0,i,j;
    var left_pre=[],left_vin=[],right_pre=[],right_vin=[];
    if(vin.length===0){
    	return null;
    }
    var head = new TreeNode(pre[0]);//pre[0]即为根节点
    for(i=0;i<vin.length;i++){
    	if(vin[i]===pre[0]){
    		root=i;//从中序遍历的数组中找到根节点的位置
    		break;
    	}
    }
    for(j=0;j<root;j++){
    	left_pre.push(pre[j+1]);//左子树的前序遍历放置在left_pre数组中
    	left_vin.push(vin[j]);//左子树的中序遍历放置在left_vin数组中
    }
    for(j=root+1;j<vin.length;j++){
    	right_pre.push(pre[j]);//右子树的前序遍历放置在right_pre数组中
    	right_vin.push(vin[j]);//右子树的中序遍历放置在right_vin数组中
    }
    head.left= reConstructBinaryTree(left_pre,left_vin);//递归遍历左子树
    head.right= reConstructBinaryTree(right_pre,right_vin);//递归遍历右子树
    
    return head;
}