携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第23天,点击查看活动详情
小偷又发现了一个新的可行窃的地区。这个地区只有一个入口,我们称之为 root 。
除了 root 之外,每栋房子有且只有一个“父“房子与之相连。一番侦察之后,聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。 如果 两个直接相连的房子在同一天晚上被打劫 ,房屋将自动报警。
给定二叉树的 root 。返回 在不触动警报的情况下 ,小偷能够盗取的最高金额 。
示例
- 示例1
输入:
3
2 3
3 1
输出:3 + 3 + 1 = 7(偷第一层和第三层)
- 示例2
输入:
3
4 5
1 3 1
输出:4 + 5 = 9(只偷第二层)
代码实现
看到树,就一定会想到递归,这道题目还多了个条件(是否选择,也就是偷还是不偷)
- 在递归过程中,如果选择当前节点,则结果为当前节点的
value加上左右子节点的不选择值 - 如果没选择当前节点,则结果为左边叶子节点的最大值(选中、不选中)加上右边叶子节点的最大值(选中、不选中)
var rob = function(root) {
const rootValue = dfs(root) // 返回一个数组,数组中只有两个元素:左边的为“选择当前节点的值”,右边的为“不选择当前节点的值”
return Math.max(...rootValue) // 返回较大的一个
}
function dfs(node) {
if(!node) return [0, 0]
const l = dfs(node.left) // 获取左子节点的最大值(也是一个拥有两个元素的数组)
const r = dfs(node.right) // 同理,获取右子节点的最大值
// 下面判断是否选择当前节点(是否要偷当前房屋)
// 如果偷的话,就加上当前节点的值(node.val),然后两个子节点是一定不能偷的,所以使用 l 和 r 的第二个元素
const selected = node.val + l[1] + r[1];
// 如果不偷的话,就拿到左子节点的最大值和右子节点的最大值,让其相加
const noSelected = Math.max(...l) + Math.max(...r)
return [selected, noSelected]
}