这是我参与8月更文挑战的第19天,活动详情查看:8月更文挑战
这个系列没啥花头,就是纯 leetcode 题目拆解分析,不求用骚气的一行或者小众取巧解法,而是用清晰的代码和足够简单的思路帮你理清题意。让你在面试中再也不怕算法笔试。
好久没做关于树的题目,来两道
162. 二叉树的直径 (diameter-of-binary-tree)
标签
- 简单
- 递归
题目
给定一棵二叉树,你需要计算它的直径长度。一棵二叉树的直径长度是任意两个结点路径长度中的最大值
。这条路径可能穿过也可能不穿过根结点。
示例 1
给定二叉树
1
/ \
2 3
/ \
4 5
返回 3, 它的长度是路径 [4,2,1,3] 或者 [5,2,1,3]。
两结点之间的路径长度是以它们之间边的数目表示。
基本思路
二叉树的题,关键是理解题意,然后思考问题的答案能用数的一些基本特性来转化吗,然后基本都能用递归来解决,比如本题,要求任意两个结点路径长度中的最大值
,其实我们就可以转化为 左右子树的最大深度和,然后加根节点的 1
- 递归函数就是,求该节点为根时的最大直径, 最后把 root 传进去就是我们需要的答案
写法实现
var diameterOfBinaryTree = function(root) {
let res = 0
const dfs = (node) => {
// 如果 node === null
if (!node) return 0
// 求左右子树的最大深度
let left = dfs(node.left)
let right = dfs(node.right)
// 最大值跟当前最大比
res = Math.max(left + right, res)
// 返回以 node 为根的最大长度 + 1 是加根节点
return Math.max(left, right) + 1
}
dfs(root)
return res
};
简单题,就是不要想的太复杂,就是两边深度相加,就是最大长度,就想象上面例子从 5(左子树) 走到 3(右子树) 你能看出最大长度就是 左右深度相加就行。
163. 把二叉搜索树转换为累加树 (convert-bst-to-greater-tree)
标签
- 中等
- BST
题目
给出二叉搜索树的根节点
,该树的节点值各不相同,请你将其转换为累加树
(Greater Sum Tree),使每个节点 node
的新值等于原树中大于或等于 node.val 的值之和。
提醒一下,二叉搜索树满足下列约束条件:
- 节点的左子树仅包含键 小于 节点键的节点。
- 节点的右子树仅包含键 大于 节点键的节点。
- 左右子树也必须是二叉搜索树。
示例 1
输入:[4,1,6,0,2,5,7,null,null,null,3,null,null,null,8]
输出:[30,36,21,36,35,26,15,null,null,null,33,null,null,null,8]
示例 2
输入:root = [0,null,1]
输出:[1,null,1]
示例 3
输入:root = [1,0,2]
输出:[3,3,2]
示例 4
输入:root = [3,2,4,1]
输出:[7,9,4,10]
基本思路
首先我们需要知道 BST 的一些性质, 根据题意知道:
- 二叉搜索树的中序遍历,访问的节点值是递增的。
- 所以这题跟中序遍历相关,能写出中序遍历模板不? 看我的这篇 一文说透二叉树遍历
注意代码中红字
// 递归方式的中序遍历
const midOrderTraversalRecursion = (root) => {
let resList = []
const midOrderTraversal = (node) => {
if(node !== null) {
// 先遍历左子树
midOrderTraversal(node.left) // ---------> (左)
// 然后访问根节点
`!!!!! (这里你可以做点啥)`
resList.push(node.val) // ---------> (根)
// 再遍历右子树
midOrderTraversal(node.right) // ---------> (右)
}
}
midOrderTraversal(root)
return resList
}
本题是累加和,其实就是改造中序遍历拉,而且注意我们这题需要 反向的中序遍历
, 所以需要改造模板,但思路基本相通的。
- 对于每一个节点,先递归它的右子树
- 再在当前节点做点什么,
累加
上当前节点值,并更新
当前节点值 - 再递归它的左子树。
写法实现
var convertBST = function(root) {
let sum = 0
let reverseinOrder = (node) => {
if (node) {
// 先遍历右子树
reverseinOrder(node.right)
// 中间做累加,更新
sum = sum + node.val
node.val = sum
// 再递归左子树
reverseinOrder(node.left)
}
}
reverseinOrder(root)
return root
};
我认为思路还算清晰了,如果有不明白欢迎留言。
另外向大家着重推荐下这个系列的文章,非常深入浅出,对前端进阶的同学非常有作用,墙裂推荐!!!核心概念和算法拆解系列
今天就到这儿,想跟我一起刷题的小伙伴可以加我微信哦 点击此处交个朋友
Or 搜索我的微信号infinity_9368
,可以聊天说地
加我暗号 "天王盖地虎" 下一句的英文
,验证消息请发给我
presious tower shock the rever monster
,我看到就通过,加了之后我会尽我所能帮你,但是注意提问方式,建议先看这篇文章:提问的智慧