LeetCode198. 打家劫舍
题目链接:198. 打家劫舍
独上高楼,望尽天涯路
dp[i]表示的是偷窃0-i房屋所能获得的最大金额。
class Solution {
public:
int rob(vector<int>& nums) {
if (nums.size() == 1) return nums[0];
vector<int> dp(nums.size(), 0);
dp[0] = nums[0];
dp[1] = max(nums[0], nums[1]);
for (int i = 2; i < nums.size(); i++) {
dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]);
}
return dp[nums.size() - 1];
}
};
慕然回首,灯火阑珊处
代码一样,题解的思路更清晰。
决定dp[i]的因素就是第i房间偷还是不偷。
如果偷第i房间,那么dp[i] = dp[i - 2] + nums[i] ,即:第i-1房一定是不考虑的,找出 下标i-2(包括i-2)以内的房屋,最多可以偷窃的金额为dp[i-2] 加上第i房间偷到的钱。
如果不偷第i房间,那么dp[i] = dp[i - 1],即考 虑i-1房,(注意这里是考虑,并不是一定要偷i-1房,这是很多同学容易混淆的点)
LeetCode213. 打家劫舍II
题目链接:213. 打家劫舍II
独上高楼,望尽天涯路
感觉算法主体部分还是打家劫舍I的思路。
慕然回首,灯火阑珊处
讨论三种情况,情况一:不包含首尾元素,情况二:不包含首元素,情况三:不包含尾元素。
分析一下可以知道,情况二和情况三包含情况一,这是因为,例如情况三,虽然包含首元素,但是最高金额不一定选首元素,所以只需要考虑情况二和情况三中最大者即可。
class Solution {
public:
int rob(vector<int>& nums) {
if (nums.size() == 1) return nums[0];
if (nums.size() == 2) return max(nums[0], nums[1]);
int result1 = robRange(nums, 0, nums.size() - 2); // 情况三
int result2 = robRange(nums, 1, nums.size() - 1); // 情况二
return max(result1, result2);
}
// 和打家劫舍的思路一样
int robRange(vector<int>& nums, int start, int end) {
vector<int> dp(nums.size());
dp[start] = nums[start];
dp[start + 1] = max(nums[start], nums[start + 1]);
for (int i = start + 2; i <= end; i++) {
dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]);
}
return dp[end];
}
};
LeetCode337. 打家劫舍III
题目链接:337. 打家劫舍III
独上高楼,望尽天涯路
树有点生疏了,挖个坑,等二刷把树复习了再来看这道题。