劍指offer04-重建二叉樹

重建二叉樹

題目描述

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

思路1

  • 在二叉樹的前序遍歷序列中,第一個數字老是樹的根節點的值。但在中序遍歷序列中,根節點的值在序列的中間,左子樹的節點值位於根節點的值的左邊,而右子樹的節點的值位於根節點的值的右邊。
  • 例如:
    前序序列{1,2,4,7,3,5,6,8} = pre
    中序序列{4,7,2,1,5,3,8,6} = in
    1. 根據當前前序序列的第一個結點肯定根結點,爲 1;
    2. 找到 1 在中序遍歷序列中的位置,爲 in[3];
    3. 切割左右子樹,則 in[3] 前面的爲左子樹, in[3] 後面的爲右子樹;
    4. 則切割後的左子樹前序序列爲:{2,4,7},切割後的左子樹中序序列爲:{4,7,2};切割後的右子樹前序序列爲:{3,5,6,8},切割後的右子樹中序序列爲:{5,3,8,6};
    5. 對子樹分別使用一樣的方法分解。

程序(java)

/**
     * code1:遞歸(傳入數組的拷貝)
     * 時間複雜度:O(n),空間複雜度:O(n)
     */
    import java.util.Arrays;
    public static TreeNode reConstructBinaryTree(int[] pre, int[] in) {
        if (pre == null || in == null || pre.length == 0 || in.length == 0) {
            return null;
        }
        if (pre.length != in.length) {
            return null;
        }

        TreeNode root = new TreeNode(pre[0]);
        for (int i = 0; i < pre.length; i++) {
            if (pre[0] == in[i]) {
                root.left = reConstructBinaryTree(Arrays.copyOfRange(pre, 1, i + 1), Arrays.copyOfRange(in, 0, i));
                root.right = reConstructBinaryTree(Arrays.copyOfRange(pre, i + 1, pre.length), Arrays.copyOfRange(in, i + 1, in.length));
            }
        }
        return root;
    }
複製代碼
/**
     * code2:遞歸(傳入子數組的邊界索引)
     * 時間複雜度:O(n),空間複雜度:O(n)
     */
    public class Solution {
    public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
        if (pre == null || pre.length == 0 ||
                in == null || in.length == 0) return null;
        return helper(pre, 0, pre.length - 1, in, 0, in.length - 1);
    }
    private TreeNode helper(int[] pre, int preL, int preR, int[] in, int inL, int inR) {
        if (preL > preR || inL > inR) {
            return null;
        }
        int rootVal = pre[preL];
        int index = 0;
        while (index <= inR && in[index] != rootVal) {
            index++;
        }
        TreeNode root = new TreeNode(rootVal);
        root.left = helper(pre, preL + 1, preL - inL + index, in, inL, index);
        root.right = helper(pre, preL - inL + index + 1, preR, in, index + 1, inR);
        return root;
    }
}
複製代碼

補充

關於Java中的Arrays.copyOfRange()方法
  1. 要使用這個方法,首先要import java.util.Arrays;
  2. 將一個原始的數組original,從下標from開始複製,複製到上標to,生成一個新的數組(8大類型基本數組)。注意這裏包括下標from,不包括上標to。
Arrays.copyOfRange(T[ ] original,int from,int to)
複製代碼
  1. 實例:

int [] s1 = {1,2,3,4,5};
int [] s2 = Arrays.copyOfRange(s1, 2, 4);
System.out.println(Arrays.toString(s2));
複製代碼
輸出 [3,4]
複製代碼

int [] s1 = {1,2,3,4,5};
int [] s2 = Arrays.copyOfRange(s1, 2, 5);
System.out.println(Arrays.toString(s2));
複製代碼
輸出 [3,4,5]
複製代碼

int [] s1 = {1,2,3,4,5};
int [] s2 = Arrays.copyOfRange(s1, 2, 2);
System.out.println(Arrays.toString(s2));
複製代碼
輸出 []
複製代碼

int [] s1 = {1,2,3,4,5};
int [] s2 = Arrays.copyOfRange(s1, 5, 5);
System.out.println(Arrays.toString(s2));
複製代碼
輸出 []
複製代碼

參考

  1. 數據結構之二叉樹
  2. 重建二叉樹(牛客網)
  3. 重建二叉樹(GitHub)
相關文章
相關標籤/搜索