这个系列没啥花头,就是纯 leetcode 题目拆解分析,不求用骚气的一行或者小众取巧解法,而是用清晰的代码和足够简单的思路帮你理清题意。让你在面试中再也不怕算法笔试。
85. 平衡二叉树 (balanced-binary-tree)
标签
- 平衡二叉树
- 简单
题目
这里不贴题了,leetcode打开就行,题目大意:
给定一个二叉树,判断它是否是高度平衡的二叉树。
本题中,一棵高度平衡二叉树定义为:
一个二叉树每个节点 的左右两个子树的高度差的绝对值
不超过 1。
示例1:
输入:root = [3,9,20,null,null,15,7]
输出:true
输入:root = [1,2,2,3,3,null,null,4,4]
输出:false
基本思路
平衡二叉树,根据定义我们知道
每个节点的左右子树高度(深度)差 不超过 1
-
我们实现一个求二叉树深度的函数
- 当节点为空时返回 0
- 要不选其左右子树更深的一条路深度 + 1 (为什么你画个图就明白了,非常简单,叶子节点左右子树都是 null,深度是 + 1,然后往上看)
-
递归去判断是否是平衡二叉树
root === null是递归出口- 左右子树深度差小于1
- 递归判断左右子树是否都平衡即可
写法实现
var isBalanced = function(root) {
if (root === null) {
return true
}
// 左右子树深度差小于1,以及左右子树都为平衡二叉,条件才会成立
return Math.abs(depth(root.left) - depth(root.right)) <= 1
&& isBalanced(root.left)
&& isBalanced(root.right)
};
// 这个就是求二叉树深度函数
function depth(root) {
if (root === null) {
return 0
}
return Math.max(depth(root.left), depth(root.right)) + 1
}
86. 二叉树的最小深度 (convert-sorted-list-to-binary-search-tree)
标签
- 二叉树
- 简单
题目
这里不贴题了,leetcode打开就行,题目大意:
给定一个二叉树,找出其最小深度。
最小深度是从根节点到[最近]叶子节点的最短路径上的
节点数量。
说明:叶子节点是指没有子节点的节点。
示例 1:
输入:root = [3,9,20,null,null,15,7]
输出:2
示例 2:
输入:root = [2,null,3,null,4,null,5,null,6]
输出:5
基本思路
其实这题还是明确最小深度从何而来。他其实是要求从根到最近叶子的最短路径,那么我们要递归求出根节点到叶子节点的深度,输出最小值即可
基本步骤
其实深度问题搞清楚这两点
- 你是要分左右子树情况
- 别忘了你递归求出来的是不包含 root 的深度,要
+ 1
写法实现
var minDepth = function(root) {
if (root === null) {
return 0
}
// 如果该节点的左右子树为空的话,深度就是另外一边的最小深度 + 1(root)
if (root.left === null) {
return minDepth(root.right) + 1
}
if (root.right === null) {
return minDepth(root.left) + 1
}
// 然后递归取最小值
return Math.min(minDepth(root.left), minDepth(root.right)) + 1
};
87. 路径总和 (path-sum)
标签
- 二叉树
- 简单
题目
给你二叉树的根节点 root 和一个表示目标和的整数 targetSum ,判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。
叶子节点 是指没有子节点的节点。
示例1:
输入:root = [5,4,8,11,null,13,4,7,2,null,null,null,1], targetSum = 22
输出:true
示例2:
输入:root = [1,2,3], targetSum = 5
输出:false
基本思路
我们每遍历到一个节点,那么我们把他看成当前节点。
假定从根节点到当前节点的值之和为 val,我们可以将这个大问题转化为一个小问题:
是否存在从当前节点的子节点到叶子的路径,满足其路径和为 sum - val。
递归最简单的思路就是抓住最小子问题,然后找到递归出口,就收了。千万不要钻进递归细节里。
或者本题用 dfs 也可求解,因为二叉树,就左右两分支,所以大多问题先想递归。
写法实现
var hasPathSum = function(root, targetSum) {
// 这题还是递归,注意第二个参数是目标和
if (root === null) {
return false
}
// 递归出口,当这个节点是叶子节点,都减到最后了判断相等就行
if (root.left === null && root.right === null) {
return root.val === targetSum
}
// 递归,每经过一个节点,就用当前和减去该节点的值,继续往下递归
return hasPathSum(root.left, targetSum - root.val)
|| hasPathSum(root.right, targetSum - root.val)
};
88. 路径总和 II (path-sum-ii)
标签
- 二叉树
- 中等
题目
这里不贴题了,leetcode打开就行,题目大意:
给你二叉树的根节点 root 和一个整数目标和 targetSum ,找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。
叶子节点 是指没有子节点的节点。
示例 1:
输入:root = [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum = 22
输出:[[5,4,11,2],[5,8,4,5]]
示例 2:
输入:root = [1,2,3], targetSum = 5
输出:[]
基本思路
DFS 不了解的同学可以看这 DFS 简介。
我们还是写一个 dfs 函数,思考为什么不用回溯了,我们要走到错误的路径上怎么办? 哈哈,多思考再看下面
原因是其实我们已经遍历了所有情况,二叉树就是左右,我们两条都试过了。
所以这题还没我们以前做的 DFS + 回溯难 对吧。
写法实现
var pathSum = function(root, targetSum) {
if (root === null) {
return []
}
let res = []
const dfs = (root, curPath, curSum) => {
// 当前和先加上当前节点值
curSum = curSum + root.val
// 当前路径也加入 Path
curPath.push(root.val)
// 加上当前值后 成功找到路径了 推进结果数组 (递归出口) 注意还要是叶子节点
if (curSum === targetSum && !root.left && !root.right) {
res.push(curPath)
} else {
// 如果还没找到,继续往其左右子树递归 加和(不是 null 的话)
if (root.left !== null) {
dfs(root.left, curPath.slice(), curSum)
}
if (root.right !== null) {
dfs(root.right, curPath.slice(), curSum)
}
}
}
dfs(root, [], 0)
return res
};
另外向大家着重推荐下这位大哥的文章,非常深入浅出,对前端进阶的同学非常有作用,墙裂推荐!!!核心概念和算法拆解系列
今天就到这儿,想跟我一起刷题的小伙伴可以加我微信哦
搜索我的微信号infinity_9368,可以聊天说地
加我暗号 "天王盖地虎" 下一句的英文,验证消息请发给我
presious tower shock the rever monster,我看到就通过,暗号对不上不加哈,加了之后我会尽我所能帮你,但是注意提问方式,建议先看这篇文章:提问的智慧