题目描述:
标签:动态规划
你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 ,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警 。
给定一个代表每个房屋存放金额的非负整数数组,计算你 在不触动警报装置的情况下 ,今晚能够偷窃到的最高金额。
代码:
思路分析:动态规划五部曲
具体思路和 198打家劫舍 一样。不同的是因为成环了,所以只能在1~n-1长度里打劫或者在2~n长度里打劫,取两者的最大值即可。
class Solution {
public int rob(int[] nums) {
int n = nums.length;
if(n == 1) return nums[0];
if(n == 2) return Math.max(nums[0],nums[1]);
int[] dp1 = new int[n-1];
int[] dp2 = new int[n-1];
dp1[0] = nums[0];
dp1[1] = Math.max(nums[0],nums[1]);
dp2[0] = nums[1];
dp2[1] = Math.max(nums[1],nums[2]);
for(int i = 2;i < n-1;i++){
dp1[i] = Math.max(dp1[i-2]+nums[i],dp1[i-1]);
}
for(int i = 2;i < n-1;i++){
dp2[i] = Math.max(dp2[i-2]+nums[i+1],dp2[i-1]);
}
return Math.max(dp1[n-2],dp2[n-2]);
}
}
另外其实可以把求dp数组部分提取出来做一个函数,实现复用!
class Solution {
public int rob(int[] nums) {
int n = nums.length;
if(n == 0) return 0;
if(n == 1) return nums[0];
int result1 = robRange(nums,0,n-2);
int result2 = robRange(nums,1,n-1);
return Math.max(result1,result2);
}
public int robRange(int[] nums,int begin,int end){
if(begin == end) return nums[begin];
int[] dp = new int[nums.length];
dp[begin] = nums[begin];
dp[begin+1] = Math.max(nums[begin],nums[begin+1]);
for(int i = begin+2;i <= end;i++){
dp[i] = Math.max(dp[i-2]+nums[i],dp[i-1]);
}
return dp[end];
}
}