LeetCode刷题 Day48
198. House Robber
You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed, the only constraint stopping you from robbing each of them is that adjacent houses have security systems connected and it will automatically contact the police if two adjacent houses were broken into on the same night.
Given an integer array nums representing the amount of money of each house, return the maximum amount of money you can rob tonight without alerting the police.
Example 1:
Input: nums = [1,2,3,1]
Output: 4
Explanation: Rob house 1 (money = 1) and then rob house 3 (money = 3).
Total amount you can rob = 1 + 3 = 4.
Example 2:
Input: nums = [2,7,9,3,1]
Output: 12
Explanation: Rob house 1 (money = 2), rob house 3 (money = 9) and rob house 5 (money = 1).
Total amount you can rob = 2 + 9 + 1 = 12.
步骤:
- dp index和value意义: index就是指当前所处的房屋 value是到当前房屋所能获取的最大值
- 递推公式: dp[i] = Math.max(dp[i - 2] + nums[i], dp[i - 1]);
- 初始化: dp[0] = nums[0], dp[1] = nums[1]。 其余为0
- 遍历顺序: 单层循环顺序遍历
- 举例:
代码:
var rob = function(nums) {
if (nums.length === 1) return nums[0];
let dp = Array(nums.length).fill(0);
dp[0] = nums[0];
dp[1] = Math.max(nums[0], nums[1]);
for (let i = 2; i < nums.length; i++) {
dp[i] = Math.max(dp[i - 2] + nums[i], dp[i - 1]);
}
return dp[nums.length - 1];
};
时间复杂度: O(n), 空间复杂度: O(n)
213. House Robber II
You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed. All houses at this place are arranged in a circle. That means the first house is the neighbor of the last one. Meanwhile, adjacent houses have a security system connected, and it will automatically contact the police if two adjacent houses were broken into on the same night.
Given an integer array nums representing the amount of money of each house, return the maximum amount of money you can rob tonight without alerting the police.
Example 1:
Input: nums = [2,3,2]
Output: 3
Explanation: You cannot rob house 1 (money = 2) and then rob house 3 (money = 2), because they are adjacent houses.
Example 2:
Input: nums = [1,2,3,1]
Output: 4
Explanation: Rob house 1 (money = 1) and then rob house 3 (money = 3).
Total amount you can rob = 1 + 3 = 4.
Example 3:
Input: nums = [1,2,3]
Output: 3
思路: 这道题要分两种场景来考虑,一种是第一个house不访问,一种是最后一个house不访问, 这样才能防止访问收尾house之后触发警报
步骤:
- dp index和value意义: index就是指当前所处的房屋 value是到当前房屋所能获取的最大值
- 递推公式: dp[i] = Math.max(dp[i - 2] + nums[i], dp[i - 1]);
- 初始化: dp[start] = nums[start], dp[start + 1] = nums[start + 1]。 其余为0
- 遍历顺序: 单层循环顺序遍历
代码:
var rob = function(nums) {
if (nums.length < 3) return Math.max(...nums);
return Math.max(helper(nums, 0, nums.length - 2), helper(nums, 1, nums.length - 1));
};
let helper = function(nums, start, end) {
let dp = Array(nums.length).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 - 2] + nums[i], dp[i - 1]);
}
return dp[end];
}
时间复杂度: O(n), 空间复杂度: O(n)
337. House Robber III
The thief has found himself a new place for his thievery again. There is only one entrance to this area, called root.
Besides the root, each house has one and only one parent house. After a tour, the smart thief realized that all houses in this place form a binary tree. It will automatically contact the police if two directly-linked houses were broken into on the same night.
Given the root of the binary tree, return the maximum amount of money the thief can rob without alerting the police.
Example 1:
Input: root = [3,2,3,null,3,null,1]
Output: 7
Explanation: Maximum amount of money the thief can rob = 3 + 3 + 1 = 7.
Example 2:
Input: root = [3,4,5,1,3,null,1]
Output: 9
Explanation: Maximum amount of money the thief can rob = 4 + 5 = 9.
思路: 这道题的技巧在于如何在递归中如何使用dp的思想。实际上结合之前打家劫舍的题目,应该可以想到 父节点和子节点是不能同时计算和的。这样,dp中应该有两个状态,取当前节点时的值,跳过当前节点的值, 所以我们需要一个长度为2的数组去记录
代码:
var rob = function(root) {
return Math.max(...helper(root));
};
let helper = function(root) {
if (!root) return [0, 0];
let left = helper(root.left);
let right = helper(root.right);
// use curr
let val1 = root.val + left[0] + right[0];
// skip curr
let val2 = Math.max(left[0], left[1]) + Math.max(right[0], right[1]);
return [val2, val1];
}