递归算法
这是leetcode中337. 打家劫舍 III ,难度为中等
题目描述
在上次打劫完一条街道之后和一圈房屋后,小偷又发现了一个新的可行窃的地区。这个地区只有一个入口,我们称之为“根”。 除了“根”之外,每栋房子有且只有一个“父“房子与之相连。一番侦察之后,聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。 如果两个直接相连的房子在同一天晚上被打劫,房屋将自动报警。
计算在不触动警报的情况下,小偷一晚能够盗取的最高金额。
示例 1:
输入: [3,2,3,null,3,null,1]
3
/ \
2 3
\ \
3 1
输出: 7
解释: 小偷一晚能够盗取的最高金额 = 3 + 3 + 1 = 7.
示例 2:
输入: [3,4,5,1,3,null,1]
3
/ \
4 5
/ \ \
1 3 1
输出: 9
解释: 小偷一晚能够盗取的最高金额 = 4 + 5 = 9.
通过次数144,016提交次数237,093
来源:力扣(LeetCode)
链接:leetcode-cn.com/problems/ho…
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
算法实现
/**
* Definition for a binary tree node.
* function TreeNode(val, left, right) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
*/
/**
* @param {TreeNode} root
* @return {number}
*/
var rob = function(root) {
//18点17分 有点不太清楚题意,好像有点明白了,就是不能让偷的房子之间右相互联系的
//也就是说不能够偷是上下级关系的房子 18点19分
//18点25分 实在是想不出来,前序遍历,后序遍历,中序遍历,动态规划,都想了一遍都不能够套进入
//18点42分 看完解析懵懵的,有递归算法和图的动态规划
//递归算法
//观察图中可以看出,如果要让一个可收获最大,分为两种情况
//第一种,抢了当前房子的,抢了以后就只能抢子房子的子房子,不然就会产生联系了
//第二种,没有抢当前房子的,可以抢房子的左右子房子,然后一次类推
//比较两种方法,返回最大值
// var sober = (rootNode) => {
// if(rootNode == null) return 0
// var the_one = rootNode.val
// //如果左边有值的话,就加上左边的子房子
// if(rootNode.left){
// the_one += sober(rootNode.left.left) + sober(rootNode.left.right)
// }
// //如果右边有值的话,就加上右边的子房子
// if(rootNode.right){
// the_one += sober(rootNode.right.left) + sober(rootNode.right.right)
// }
// //第二种方法,就是当前的左子树和右子树之和
// var the_two = sober(rootNode.left) + sober(rootNode.right)
// return Math.max(the_one,the_two)
// }
// return sober(root)
//哎呀,超出时间限制,😅!!! 18点53分
//又看了一遍的答案,然后发现它加入了记忆的方法
var map = new Map();
//温故一下map的使用
//map保存的是 键 -> 值
//map.has(key) 表示 是否存在 键
//map.size 输出键的多少
//map.keys() 输出所有的键,这里输出的不是数组,如果要当成数组使用的话,需要进行转化
//map.values() 输出所有键对应的值
//map.get(key) 获取键对应的值,比如这道题就是获取rootNode对应的抢劫后的money
var sober = (rootNode) => {
if(rootNode == null) return 0
//如果这个节点存在与map中的话,就返回对应的值
if(map.has(rootNode)) return map.get(rootNode)
var the_one = rootNode.val
//如果左边有值的话,就加上左边的子房子
if(rootNode.left){
the_one += sober(rootNode.left.left) + sober(rootNode.left.right)
}
//如果右边有值的话,就加上右边的子房子
if(rootNode.right){
the_one += sober(rootNode.right.left) + sober(rootNode.right.right)
}
//第二种方法,就是当前的左子树和右子树之和
var the_two = sober(rootNode.left) + sober(rootNode.right)
//保存结果
var res = Math.max(the_one,the_two)
//设置节点的值
map.set(rootNode,res)
return res
}
return sober(root)
};
最后
这是我2022年分享的「leetcode」第NO.2篇文章。