1. 题目
你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都围成一圈,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。
给定一个代表每个房屋存放金额的非负整数数组,计算你在不触动警报装置的情况下,能够偷窃到的最高金额。
类似题目:
LeetCode 198. 打家劫舍(DP)
LeetCode 337. 打家劫舍 III(记忆化+递归)
2. 动态规划解题
在前一题LeetCode 198 的前提下,换一种思考
- 第一个房间偷,那么最后一个不偷,dp数组从0(第一个)到n-2(倒数第2个),获得的最大金额 m1
- 第一个房间不偷,那么最后一个偷,dp数组从1(第二个)到n-1(倒数第1个),获得的最大金额 m2
- 取 max(m1,m2)为最大金额
class Solution {
public:
int rob(vector<int>& nums) {
int n = nums.size(), i, m1, m2;
if(n == 0)
return 0;
else if(n == 1)
return nums[0];
else if(n == 2)
return max(nums[0],nums[1]);
int dp[n] = {0};
//第一间房子,偷,那么最后一间n-1不能偷
dp[0] = nums[0];
dp[1] = max(nums[0],nums[1]);
for(i = 2; i <= n-2; ++i)
{
dp[i] = max(dp[i-2]+nums[i], dp[i-1]);
}
m1 = dp[n-2];
//第一间房子,不偷,那么最后一间n-1能偷
dp[1] = nums[1];
dp[2] = max(nums[1],nums[2]);
for(i = 3; i <= n-1; ++i)
{
dp[i] = max(dp[i-2]+nums[i], dp[i-1]);
}
m2 = dp[n-1];
return max(m1,m2);
}
};
- 观察到上面转态转移公式只跟前两个转态有关,可以进行压缩,节省空间,见前一篇 LeetCode 198,不再写出。