普通版:首位两个房子不是连在一起的。
题目:
Note: This is an extension of House Robber.
After robbing those houses on that street, the thief has found himself a new place for his thievery so that he will not get too much attention. This time, all houses at this place are arranged in a circle. That means the first house is the neighbor of the last one. Meanwhile, the security system for these houses remain the same as for those in the previous street.
Given a list of non-negative integers representing the amount of money of each house, determine the maximum amount of money you can rob tonight without alerting the police.
Credits:
Special thanks to @Freezen for adding this problem and creating all test cases.
Subscribe to see which companies asked this question
代码:
class Solution {
public:
int rob(vector& nums) {
int size = nums.size();
if (size == 0)return 0;
if (size == 1)return nums[0];
vectordp(size,0);
dp[0] = nums[0];
dp[1] = max(nums[0],nums[1]);
//对于每个红包都有两种情况,要么拿要么不拿
for (int i = 2; i < size;i++){
dp[i] = max(dp[i-1],dp[i-2]+nums[i]);
}
return dp[size-1];
}
};
dp[i] = max(dp[i-1],dp[i-2]+nums[i])
其中dp[i]是从数组nums下标为0到下标为i可盗得的最大金额,注意数组元素nums[i]不一定包含在dp[i]里!
这个转态转化方程的逻辑是:对于每一个数组元素nums[i]要么不加入到dp[i]中,要么加入到dp[i]中;显然,如果不将nums[i]加入到dp[i]中,则dp[i]=dp[i-1];
如果将nums[i[加入到dp[i]中,情况有些复杂,这是dp[i-2]+nums[i],为什么?我们知道小偷不能偷盗连续的两个房子,再加入nums[i]时,我们知道nums[i-1]有没有加入到
dp[i-1],如果nums[i-1]加入到了dp[i-1]中,那么dp[i]=dp[i-2]+nums[i];如果nums[i-1]没有加入到了dp[i-1]中,那么dp[i]=dp[i-1]+nums[i]或dp[i]=dp[i-1]+nums[i]都可,因为在
nums[i-1]没有加入到dp[i-1]的时候,dp[i-1]=订票dp[i-2],所以此时,dp[i]=dp[i-2]+nums[i]依然成立!!!!
升级版:robber house II
题目:
Note: This is an extension of House Robber.
After robbing those houses on that street, the thief has found himself a new place for his thievery so that he will not get too much attention. This time, all houses at this place are arranged in a circle. That means the first house is the neighbor of the last one. Meanwhile, the security system for these houses remain the same as for those in the previous street.
Given a list of non-negative integers representing the amount of money of each house, determine the maximum amount of money you can rob tonight without alerting the police.
升级版多了一个附加条件:一条街上的首尾两个房子是相连的!!!这样我们确定第一个房子和最后一个房子只能盗窃一个,所以就将上面的算法执行两遍,第一遍将原始数组的第一个元素除去,第二遍将数组的最后一个元素除去,最后取两种情况的较大值!!!
代码:
class Solution {
public:
int rob(vector& nums) {
int size = nums.size();
if (size == 0)return 0;
if (size == 1)return nums[0];
if (size == 2)return max(nums[0],nums[1]);
vectordp_head(size-1,0);
vectordp_tail(size-1,0);
vectornum_head, num_tail;
int max_head=0, max_tail=0;
for (int i = 0; i < size;i++){
if(i!=size-1)num_head.push_back(nums[i]);
if(i!=0)num_tail.push_back(nums[i]);
}
//先计算前面
dp_head[0] = num_head[0];
dp_head[1] = max(num_head[0],num_head[1]);
for (int i = 2; i < size-1;i++)dp_head[i] = max(dp_head[i-1],dp_head[i-2]+num_head[i]);
max_head=dp_head[size-2];
//再计算尾部
dp_tail[0] = num_tail[0];
dp_tail[1] = max(num_tail[0],num_tail[1]);
for (int i = 2; i < size-1; i++)dp_tail[i] = max(dp_tail[i - 1], dp_tail[i - 2] + num_tail[i]);
max_tail = dp_tail[size - 2];
return max_head>max_tail ? max_head : max_tail;
}
};