上篇文章 手把手教你刷二叉树(第一篇) 连刷了三道二叉树题目,不少读者直呼内行。其实二叉树相关的算法真的不难,本文再来三道,手把手带你看看树的算法到底怎么作。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;}
至此,这道题就作完了,仍是挺简单的对吧,下面看两道更困难的常见算法题:让你用前序/中序遍历结果还原二叉树,以及用后序/中序遍历结果还原二叉树。