算法與數(shù)據(jù)結(jié)構(gòu):二叉樹重建問題

說明

根據(jù)中序遍歷和后序遍歷重建二叉樹

鏈接地址:LeetCode 106. Construct Binary Tree from Inorder and Postorder Traversal

特別注意,本題的約束條件中,一定要保證inorder 和 postorder 都由不同的值組成。由于

中序遍歷的順序是:左 -> 中 -> 右

后序遍歷的順序是:左 -> 右 -> 中

所以對一棵樹,其中序遍歷的樣子如下

后序遍歷的樣子如下

定義遞歸函數(shù)

TreeNode f(中序遍歷結(jié)果, int L1, int R1, 后序遍歷結(jié)果, int L2, int R2)

遞歸含義表示:中序遍歷的L1...R1和后序遍歷L2...R2構(gòu)造出的二叉樹,返回根節(jié)點。

所以主函數(shù)調(diào)用

f(inorder, 0, L, postorder, 0, L);

即為答案。

接下來實現(xiàn)這個遞歸函數(shù),由于后序遍歷的最后一個節(jié)點就是樹的根節(jié)點,所以

// 樹的根節(jié)點
樹的根節(jié)點 = new TreeNode(后序遍歷最后一個節(jié)點);

樹的根節(jié)點在中序遍歷的節(jié)點位置假設(shè)在如下 index 位置

那么在中序遍歷中,左樹為[L1......index - 1]。

中序遍歷的剩下部分用來構(gòu)造右樹:[index + 1, R1],

在后序遍歷中,左樹為[L2......L2 + index - L1 - 1]

后序遍歷的剩下部分用來構(gòu)造右樹:[L2 + index - L1, R2 - 1]

由于要記錄某個節(jié)點在中序遍歷中的位置,所以需要準備一個哈希表,用于存某個元素在中序遍歷的位置。

        int L = inorder.length - 1;
        Map<Integer, Integer> m = new HashMap<>();
        for (int i = 0; i <= L; i++) {
            m.put(inorder[i], i);
        }

完整代碼如下

class Solution {
    public static TreeNode buildTree(int[] inorder, int[] postorder) {
        if (null == postorder || inorder == null || postorder.length != inorder.length) {
            return null;
        }
        int L = inorder.length - 1;
        Map<Integer, Integer> m = new HashMap<>();
        for (int i = 0; i <= L; i++) {
            m.put(inorder[i], i);
        }
        return f(inorder, 0, L, postorder, 0, L, m);
    }

    private static TreeNode f(int[] inorder, int L1, int R1, int[] postorder, int L2, int R2, Map<Integer, Integer> m) {
        // 這種
        if (L2 > R2) {
            return null;
        }
        TreeNode root = new TreeNode(postorder[R2]);
        // 如果只有一個節(jié)點,則直接返回
        if (L2 == R2) {
            return root;
        }
        int index = m.get(postorder[R2]);
        root.left = f(inorder, L1, index - 1, postorder, L2, L2 + index - L1 - 1, m);
        root.right = f(inorder, index + 1, R1, postorder, L2 + index - L1, R2 - 1, m);
        return root;
    }
}

根據(jù)先序遍歷和中序遍歷重建二叉樹

鏈接地址:LeetCode 105. Construct Binary Tree from Preorder and Inorder Traversal

對于一棵樹,中序遍歷的樣子如下

先序遍歷的樣子如下

而且,先序遍歷的第一個節(jié)點,就是根節(jié)點,然后定位根節(jié)點在中序遍歷的位置,假設(shè)在 index 位置,則

中序遍歷中,左樹為[L2.......index - 1],剩余部分[index + 1.......R2]去構(gòu)造右樹。

先序遍歷中,左樹為[L1 + 1......index - L2 + L1],剩余部分[index - L2 + L1 + 1......R1]去構(gòu)造右樹。

完整代碼如下

class Solution {
     public static TreeNode buildTree(int[] preorder, int[] inorder) {
        if (null == preorder || inorder == null || preorder.length != inorder.length) {
            return null;
        }
        int L = inorder.length - 1;
        Map<Integer, Integer> m = new HashMap<>();
        for (int i = 0; i <= L; i++) {
            m.put(inorder[i], i);
        }
        return f(preorder, 0, L, inorder, 0, L, m);
    }

    private static TreeNode f(int[] preorder, int L1, int R1, int[] inorder, int L2, int R2, Map<Integer, Integer> m) {
        if (L1 > R1) {
            return null;
        }
        TreeNode root = new TreeNode(preorder[L1]);
        if (L1 == R1) {
            return root;
        }
        int index = m.get(preorder[L1]);
        root.left = f(preorder, L1 + 1, index - L2 + L1, inorder, L2, index - 1, m);
        root.right = f(preorder, index - L2 + L1 + 1, R1, inorder, index + 1, R2, m);
        return root;
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容