思路:
1. 一个房子都不抢: 0 收益
2. 抢第一个房子: nums【0】收益
3. 抢第二个房子:不能抢第一个房子,最大收益为Math.Max(dp[1], dp[0]+nums[1]);
4. 以上为通式,开始迭代:
public int rob(int[] nums) {
//计算房子的个数
int len = nums.length;
//若没有房子可以抢,返回收益0
if(len == 0){
return 0;
}
//新建动态数据,记录每一次抢房子的收益
int[] dp = new int[len+1];
//若不抢,则收益为0
dp[0] = 0;
//抢第一间房子,收益为nums[0]
dp[1] =nums[0];
//抢第二个房子及以上,比较前一次和前两次+当前房子的收益的最大值。即为当前抢房子的收益最大值
for(int i = 2; i < len+1; i++){
dp[i] = Math.max(dp[i-1], dp[i-2] + nums[i-1]);
}
//返回最后一个房子的收益
return dp[len];
}
思路:
这个是基于抢房子的变体, 房子连成了一个圈,即首尾相连,相邻两个房子不能抢
所以,当抢了第一个房子,就不能抢最后一个房子。
基于以上分析,我们可以把抢房子的通式分成两个算法。
1. rob1()-----》抢第一个房子,不抢最后一个房子
2. rob0()-----》不抢第一个房子,从第二个房子到最后可以房子都可抢(相邻除外)
3. 返回 rob1()/rob0()算法的最大值,即为这个题的答案
public int rob(int[] nums) {
//若房子个数为0,最大收益为0
if(nums.length == 0){
return 0;
}else if(nums.length ==1){
//若只有一个房子,则最大收益为当前房子
return nums[0];
}
//比较抢第一个房子和不抢第一个房子的最大收益
return Math.max(rob0(nums), rob1(nums));
}
//抢第一个房子
private int rob0(int[] nums){
//记录前一个抢的收益值
int prev = 0;
//记录当前的最大收益
int cur = 0;
//抢第一个房子,即不抢最后一个房子
for(int i = 0; i < nums.length -1; i++){
//临时变量储存当前的最大受益值
int temp = cur;
//更新最大收益, 比较若抢当前房子的所有收益和现在收益的最大值
//若现在收益大于抢当前房子的收益,则不抢当前房子
cur = Math.max(prev+ nums[i], cur);
//更新前一个收益值为temp储存的除此cur的值
prev = temp;
}
//返回当前收益的最大值
return cur;
}
//不抢第一个房子
private int rob1(int[] nums){
int prev = 0;
int cur = 0;
for(int i =1; i < nums.length; i++){
int temp = cur;
cur = Math.max(prev+ nums[i], cur);
prev = temp;
}
return cur;
}