题目:
你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。
给定一个代表每个房屋存放金额的非负整数数组,计算你在不触动警报装置的情况下,能够偷窃到的最高金额。
示例 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 。
刚开始自己想的是直接把数组奇数项和偶数项的总和相加,然后取最大的值。忽略了可能是相隔两个数相加。
动态规划算法通常用于求解具有某种最优性质的问题。在这类问题中,可能会有许多可行解。每一个解都对应于一个值,我们希望找到具有最优值的解。动态规划算法其基本思想也是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。
本题是要求解长度为N的数组连续不相邻元素和的最大值。记f(n)为数组长度为n时的最大值,则由递推关系可知,f(n)=max{f(n-1),f(n-2)+nums(n-1)}。这样一来,将大的问题分解为小问题求解。代码如下:
class Solution {
public int rob(int[] nums) {
if(nums==null||nums.length==0)
return 0;
int N=nums.length;
int[]re=new int[N];
if(N==1)
return nums[0];
if(N==2)
return nums[0]>nums[1]?nums[0]:nums[1];
for(int i=0;i<N;i++)
{
if(i==0)
re[i]=nums[i];
else if(i==1)
re[i]=Math.max(re[i-1],nums[i]);
else
{
re[i]=Math.max(re[i-1],re[i-2]+nums[i]);
}
}
return re[N-1]>re[N-2]?re[N-1]:re[N-2];
}
}
以下是提交的最快的方法:
基本思想是一样的,区别是递推的时候不是利用数组来做的。更简单和好理解。
class Solution {
public int rob(int[] nums) {
if(nums==null||nums.length<1){
return 0;
}
int n=nums.length;
if(n==1){
return nums[0];
}
if(n==2){
return Math.max(nums[1],nums[0]);
}
int f_n=0;
int f_n_1=Math.max(nums[1],nums[0]);
int f_n_2=nums[0];
int i=2;
while(i<n){
f_n=Math.max(f_n_1,f_n_2+nums[i]);
f_n_2=f_n_1;
f_n_1=f_n;
i++;
}
return f_n;
}
}