题目描述
原题链接:213. 打家劫舍 II
解题思路
本题与 198. 打家劫舍(动态规划) 的区别在于,此次的要求为环形列表,而198里的是线性链表。对于环形链表的解题思路是将环形进行线性化,分情况进行讨论。
例如,对nums = [1,2,3,4,1]
- 情况一:范围在[2,3,4]中进行选择
- 情况二:范围在[1,2,3,4]中进行选择
- 情况三:范围在[2,3,4,1]中进行选择
可以发现,情况二和三会包含情况一,因此我们只需分别求情况二和情况三,得到的最大情况,然后再对二者取最大值,即可。
class Solution {
public:
int robRange(vector<int>& nums, int start, int end) {
if(start == end) return nums[start];
int dp[101] = {0};
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 - 1], dp[i - 2] + nums[i]);
}
return dp[end];
}
int rob(vector<int>& nums) {
if(nums.size() == 1) return nums[0];
int dp1 = robRange(nums, 0, nums.size() - 2);
int dp2 = robRange(nums, 1, nums.size() - 1);
return max(dp1, dp2);
}
};
参考文章:213. 打家劫舍 II
另一写法
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 n = nums.size();
vector<int> dp1(n);
vector<int> dp2(n);
dp1[0] = nums[0], dp1[1] = max(nums[0], nums[1]);
dp2[0] = nums[1], dp2[1] = max(nums[1], nums[2]);
for(int i = 2; i < n - 1; i++) {
dp1[i] = max(dp1[i - 1], dp1[i - 2] + nums[i]);
}
for(int i = 3; i < n; i++) {
dp2[i - 1] = max(dp2[i - 2], dp2[i - 3] + nums[i]);
}
// 因为各自只有n-1个数
return max(dp1[n - 2], dp2[n - 2]);
}
};