你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上 被小偷闯入,系统会自动报警。 给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。 示例 1: 输入:[1,2,3,1] 输出:4 解释:偷窃 1 号房屋 (金额 = 1) ,然后偷窃 3 号房屋 (金额 = 3)。 偷窃到的最高金额 = 1 + 3 = 4 。 示例 2: 输入:[2,7,9,3,1] 输出:12 解释:偷窃 1 号房屋 (金额 = 2), 偷窃 3 号房屋 (金额 = 9),接着偷窃 5 号房屋 (金额 = 1)。 偷窃到的最高金额 = 2 + 9 + 1 = 12 。 提示: 1 <= nums.length <= 100 0 <= nums[i] <= 400 Related Topics 数组 动态规划
该思路来自于leetcode上一个老哥写的非常详细的动态规划思路,可以看原文
class Solution {
//f(k)=max(f(k-1),(f(k-2)+curr))
public int rob(int[] nums) {
if (nums.length==0){
return 0;
}
final int length = nums.length;
int[] money=new int[length+1];
money[0]=0;
money[1]=nums[0];
for (int i = 2; i <= length; i++) {
money[i]=Math.max(money[i-1],(money[i-2]+nums[i-1]));
}
return money[length];
}
}
空间优化是动态规划问题的进阶内容了。对于初学者来说,可以不掌握这部分内容。
空间优化的基本原理是,很多时候我们并不需要始终持有全部的 DP 数组。对于小偷问题,我们发现,最后一步计算 f(n)f(n) 的时候,实际上只用到了 f(n-1)f(n−1) 和 f(n-2)f(n−2) 的结果。n-3n−3 之前的子问题,实际上早就已经用不到了。那么,我们可以只用两个变量保存两个子问题的结果,就可以依次计算出所有的子问题。
class Solution {
//f(k)=max(f(k-1),(f(k-2)+curr))
public int rob(int[] nums) {
if (nums.length==0){
return 0;
}
final int length = nums.length;
int ppre=0,pre=nums[0], curr=nums[0];
for (int i = 2; i <= length; i++) {
curr =Math.max(pre,(ppre+nums[i-1]));
ppre=pre;
pre= curr;
}
return curr;
}
}