1. 程式人生 > 實用技巧 >東哥手把手帶你刷二叉樹(第二期)

東哥手把手帶你刷二叉樹(第二期)

東哥手把手帶你刷二叉樹(第二期)

讀完本文,你不僅學會了演算法套路,還可以順便去 LeetCode 上拿下如下題目:

654.最大二叉樹

105.從前序與中序遍歷序列構造二叉樹

106.從中序與後序遍歷序列構造二叉樹

-----------

上篇文章 手把手教你刷二叉樹(第一篇) 連刷了三道二叉樹題目,很多讀者直呼內行。其實二叉樹相關的演算法真的不難,本文再來三道,手把手帶你看看樹的演算法到底怎麼做。

先來複習一下,我們說過寫樹的演算法,關鍵思路如下:

把題目的要求細化,搞清楚根節點應該做什麼,然後剩下的事情拋給前/中/後序的遍歷框架就行了,我們千萬不要跳進遞迴的細節裡,你的腦袋才能壓幾個棧呀。

也許你還不太理解這句話,我們下面來看例子。

構造最大二叉樹

先來道簡單的,這是力扣第 654 題,題目如下:

函式簽名如下:

TreeNode constructMaximumBinaryTree(int[] nums);

按照我們剛才說的,先明確根節點做什麼?對於構造二叉樹的問題,根節點要做的就是把想辦法把自己構造出來

我們肯定要遍歷陣列把找到最大值 maxVal,把根節點 root 做出來,然後對 maxVal 左邊的陣列和右邊的陣列進行遞迴呼叫,作為 root 的左右子樹。

按照題目給出的例子,輸入的陣列為 [3,2,1,6,0,5],對於整棵樹的根節點來說,其實在做這件事:

TreeNode constructMaximumBinaryTree([3,2,1,6,0,5]) {
    // 找到陣列中的最大值
    TreeNode root = new TreeNode(6);
    // 遞迴呼叫構造左右子樹
    root.left = constructMaximumBinaryTree([3,2,1]);
    root.right = constructMaximumBinaryTree([0,5]);
    return root;
}

PS:我認真寫了 100 多篇原創,手把手刷 200 道力扣題目,全部發布在 labuladong的演算法小抄,持續更新。建議收藏,按照我的文章順序刷題,掌握各種演算法套路後投再入題海就如魚得水了。

再詳細一點,就是如下偽碼:

TreeNode constructMaximumBinaryTree(int[] nums) {
    if (nums is empty) return null;
    // 找到陣列中的最大值
    int maxVal = Integer.MIN_VALUE;
    int index = 0;
    for (int i = 0; i < nums.length; i++) {
        if (nums[i] > maxVal) {
            maxVal = nums[i];
            index = i;
        }
    }

    TreeNode root = new TreeNode(maxVal);
    // 遞迴呼叫構造左右子樹
    root.left = constructMaximumBinaryTree(nums[0..index-1]);
    root.right = constructMaximumBinaryTree(nums[index+1..nums.length-1]);
    return root;
}

看懂了嗎?對於每個根節點,只需要找到當前 nums 中的最大值和對應的索引,然後遞迴呼叫左右陣列構造左右子樹即可

明確了思路,我們可以重新寫一個輔助函式 build,來控制 nums 的索引:

/* 主函式 */
TreeNode constructMaximumBinaryTree(int[] nums) {
    return build(nums, 0, nums.length - 1);
}

/* 將 nums[lo..hi] 構造成符合條件的樹,返回根節點 */
TreeNode build(int[] nums, int lo, int hi) {
    // base case
    if (lo > hi) {
        return null;
    }

    // 找到陣列中的最大值和對應的索引
    int index = -1, maxVal = Integer.MIN_VALUE;
    for (int i = lo; i <= hi; i++) {
        if (maxVal < nums[i]) {
            index = i;
            maxVal = nums[i];
        }
    }

    TreeNode root = new TreeNode(maxVal);
    // 遞迴呼叫構造左右子樹
    root.left = build(nums, lo, index - 1);
    root.right = build(nums, index + 1, hi);
    
    return root;
}

至此,這道題就做完了,還是挺簡單的對吧,下面看兩道更困難的常見演算法題:讓你用前序/中序遍歷結果還原二叉樹,以及用後序/中序遍歷結果還原二叉樹。

通過前序和中序/後序和中序遍歷結果構造二叉樹

_____________

本文只能在 labuladong 公眾號檢視,關注後可直接搜尋本站內容:

相關推薦: