【劍指offer】【4】根據前序和中序結果,重建二叉樹

love_Aym發表於2018-06-06

題目:

輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建出該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。例如輸入前序遍歷序列{1,2,4,7,3,5,6,8}和中序遍歷序列{4,7,2,1,5,3,8,6},則重建二叉樹並返回。


1、分析原理:

        根據前序和中序的特性,前序序列的一個元素就是樹的根元素,那麼在中序序列找到相應的元素。找到後該元素前面所有元素都是左子樹元素,後面元素都是右子樹元素。那麼此時跟節點的pleft就是左子樹返回的結果,pright就是右子樹返回的結果,使之遞迴即可,遞迴出口就是前序區間只有一個元素時。 

這裡寫圖片描述
2、思路一:前序和中序必須結合搭配
使用遞迴,每次分清根結點、左子樹、右子樹,遞迴進行構建。

先序遍歷第一個位置肯定是根節點node,中序遍歷的根節點位置在中間p,在p左邊的肯定是node的左子樹的中序陣列,p右邊的肯定是node的右子樹的中序陣列。

重構函式(前序陣列,前序陣列頭,前序陣列尾,中序陣列,中序陣列頭,中序陣列尾);

根據前序陣列的第一個值遍歷中序陣列,找到之後即可分清前序和中序陣列中左子樹和右子樹的組成部分,得到四個新的陣列。
新左子樹:前序部分、中序部分
新右子樹:前序部分、中序部分

注意:陣列的邊界

找到左右子樹之後,當成新的前序中序陣列傳入重構函式進進一步構建,遞迴! 


/**
 * Definition for binary tree
 * public class TreeNode {
 *     int val;
 *     TreeNode left;  //左子樹
 *     TreeNode right; //右子樹
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public TreeNode reConstructBinaryTree(int [] pre,int [] in) {  //輸入前序中序陣列
        return reConBTree(pre,0,pre.length-1,in,0,in.length-1);
    }
    //使用遞迴不斷尋找根節點、左子樹、右子樹
    //每次都輸入新的樹的前序和後序陣列
    public TreeNode reConBTree(int[] pre, int preleft, int preright, int[] in, int inleft, int inright){
        if(preleft > preright || inleft > inright){  //陣列遍歷完畢
            return null;
        }
        //新建一個TreeBTree
        TreeNode root = new TreeNode(pre[preleft]);
        //遍歷中序陣列,找到根節點,和左右子樹
        for(int i=0; i < in.length; i++){
            if(in[i] == pre[preleft]){
                //重構左子樹,使用遞迴
                root.left = reConBTree(pre, preleft+1, preleft+i-inleft, in, inleft, i-1);
                //重構右子樹,使用遞迴
                root.right = reConBTree(pre, preleft+i-inleft+1, preright, in, i+1, inright);
            }
        }
        return root;
    }
}

相關文章