上篇文章 手把手教你刷二叉樹(第一篇) 連刷了三道二叉樹題目,不少讀者直呼內行。其實二叉樹相關的算法真的不難,本文再來三道,手把手帶你看看樹的算法到底怎麼作。git
先來複習一下,咱們說過寫樹的算法,關鍵思路以下:算法
把題目的要求細化,搞清楚根節點應該作什麼,而後剩下的事情拋給前/中/後序的遍歷框架就好了,咱們千萬不要跳進遞歸的細節裏,你的腦殼才能壓幾個棧呀。數組
也許你還不太理解這句話,咱們下面來看例子。框架
先來道簡單的,這是力扣第 654 題,題目以下:函數
函數簽名以下:ui
TreeNode constructMaximumBinaryTree(int[] nums);
按照咱們剛纔說的,先明確根節點作什麼?對於構造二叉樹的問題,根節點要作的就是把想辦法把本身構造出來。spa
咱們確定要遍歷數組把找到最大值 maxVal
,把根節點 root
作出來,而後對 maxVal
左邊的數組和右邊的數組進行遞歸調用,做爲 root
的左右子樹。code
按照題目給出的例子,輸入的數組爲 [3,2,1,6,0,5]
,對於整棵樹的根節點來講,其實在作這件事:orm
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;}
再詳細一點,就是以下僞碼:
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;}
至此,這道題就作完了,仍是挺簡單的對吧,下面看兩道更困難的常見算法題:讓你用前序/中序遍歷結果還原二叉樹,以及用後序/中序遍歷結果還原二叉樹。