提示:努力生活,开心、快乐的一天
题目链接:198. 打家劫舍
动态规划
var rob = function(nums) {
let len = nums.length
let dp = [nums[0], Math.max(nums[0], nums[1])]
for (let i = 2; i < len; i++){
dp[i] = Math.max(dp[i-1],dp[i-2]+nums[i])
}
return dp[len-1]
};
当前房屋偷与不偷取决于 前一个房屋和前两个房屋是否被偷了,是非常经典的DP题目
题目链接:213. 打家劫舍 II
动态规划
var rob = function (nums) {
let len = nums.length
if (len === 0) return 0
if (len === 1) return nums[0]
//不要尾 情况二
let result2 = robRange(nums, 0, len - 2)
//不要头 情况三
let result1 = robRange(nums, 1, len - 1)
return Math.max(result1, result2)
};
//与之前的没有环形的数组一样
const robRange = (nums, start, end) => {
if (end === start) return nums[start]
let len = nums.length
let dp = new Array(len).fill(0)
dp[start] = nums[start]
dp[start+1] = Math.max(nums[start],nums[start+1])
for (let i = start+2; i <= end; i++) {
dp[i] = Math.max(dp[i - 1], dp[i - 2] + nums[i])
}
return dp[end]
};
三种情况,情况一包含在情况二和情况三中。另外调用原来的方法需要进行改动,有数组的起始和结束为止的标识
题目链接:337. 打家劫舍 III
动态规划
const rob = root => {
// 后序遍历函数
const postOrder = node => {
// 递归出口
if (!node) return [0, 0];
// 遍历左子树
const left = postOrder(node.left);
// 遍历右子树
const right = postOrder(node.right);
// 不偷当前节点,左右子节点都可以偷或不偷,取最大值
const DoNot = Math.max(left[0], left[1]) + Math.max(right[0], right[1]);
// 偷当前节点,左右子节点只能不偷
const Do = node.val + left[0] + right[0];
// [不偷,偷]
return [DoNot, Do];
};
const res = postOrder(root);
// 返回最大值
return Math.max(...res);
};
只不过平时我们习惯了在一维数组或者二维数组上推导公式,一下子换成了树,就需要对树的遍历方式足够了解!
打家劫舍还不错,思路捋清楚以后,可以举一反三啦,打家劫舍III是真的难啊