题目链接:打家劫舍
题目描述:一个非负整数数组,相邻的两个数不能相加,求最大的和是多少。
思路:
一、最开始分析找规律找到的情况是,因为相邻的数不能相加,所以第i个数只能在之后加上第i+2或第i+3个数。哪个大加哪个。
所以,到第i个数的和,只跟第i-2和第i-3个数有关。即sum[i]=Max(sum[i-2],sum[i-3])+nums[i]。
时间O(n),空间O(1)
JavaScript代码如下:
var rob = function(nums) {
const len=nums.length;
if(len==1)
return nums[0];
if(len==2)
return nums[0]>nums[1]?nums[0]:nums[1];
if(len==3)
return nums[0]+nums[2]>nums[1]?nums[0]+nums[2]:nums[1];
let max=0;
for(let i=2;i<nums.length;i++){
if(i==2){
nums[2]+=nums[0];
if(nums[2]>max)
max=nums[2];
}
else{
nums[i]=nums[i-2]+nums[i]>nums[i-3]+nums[i]?nums[i-2]+nums[i]:nums[i-3]+nums[i];
if(nums[i]>max)
max=nums[i];
}
}
return max;
};
二、看完题解之后仔细分析,发现这是一个简单的动态规划
n个数的最大和,有两种情况,取第n个数,那么和是n-2个数的最大和加上第n个数,不取第n个数,那么和是n-1个数的最大和。
即状态转移方程为:dp[n]=Max(dp[n-1],dp[n-2]+nums[n-1])。
边界条件是dp[0]=0,dp[1]=nums[0]。
因为dp[n]只和前面的两个数dp[n-1],dp[n-2]有关。所以没必要开一个动态规划数组,只需要两个变量动态维护即可。时间O(n),空间O(1)。
JavaScript代码:
const length=nums.length;
if(length==0)
return 0;
if(length==1)
return nums[0];
let a=0,b=nums[0];
let tep;
for(let i=2;i<=length;i++){
tep=b>a+nums[i-1]?b:a+nums[i-1];
a=b;
b=tep;
}
return tep;