劍指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;
}