不清楚动态规划是什么的同学先看看我的上一篇
目录
1:打家劫舍
思路解析:
(1)当只有一个房屋时,最大金额就是这个了,即:maxprofit=nums[0]
(2)当有两个房屋时,选择两个房屋中金额最高的,即:maxprofit=max(nums[0],nums[1])
(3)我们重点要考虑的问题是,当房屋的数量>2个时的情况:
我们就要找到递推关系:既然不能间隔,那么情况应该分为两种:
1:我既然拿到了nums[i-1],我就不能拿nums[i]
2:我拿了nums[i-2],我还能拿nums[i]
是不是有点熟悉了^ ^
没错青蛙跳台阶问题!
只不过我们还要动态规划在这两者中选择最大值:
代码实现:核心的递推公式!
dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]);
完整代码:
class Solution {
public:
int rob(vector<int>& nums){
if (nums.empty())
{
return 0;
}
int size = nums.size();
if (size == 1)
{
return nums[0];
}
vector<int> dp = vector<int>(size, 0);
dp[0] = nums[0];
dp[1] = max(nums[0], nums[1]);
for (int i = 2; i < size; i++)
{
dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]);
}
return dp[size - 1];
}
};
问:为什么返回的是dp[size-1]?
答:因为数组的最后一位的索引是size-1
2:打家劫舍||
思路解析:
这道题的的难点就在于,它是一个环状的,因此在首尾处要特别小心,不能既选首又选尾!
这就是与上题的区别,那么我们就可以对这个区别进行分类讨论,让它成为我们的上一题的想法!
1:首先创建两个容器
f(n+1)和g(n+1) ->为什么要定义n+1的大小? ->为了好看(下标对应)
f(1)=nums[0]; -> 表示从原数组的首位置开始
g(2) =nums[1]: ->表示从原数组索引为1的位置开始
2:f(n+1)的递推
for (int i = 2; i <= n - 1; i++)
f[i] = max(f[i - 1], f[i - 2] + nums[i-1]);//区间[1,n-1]的最大值
由此可知f(2)=max(nums[0],nums[1]) ->f(2)才是真正的开始!
f(3)=max(f[2],nums[0]+nums[2]) //接着递推
3:g(n+1)的递推
for (int i = 3; i <= n; i++)
g[i] = max(g[i - 1], g[i - 2] + nums[i-1]);//区间[2,n]的最大值
由此可知g(3)=max(nums[1],nums[2]) ->g(3)才是真正的开始!
g(4)=max(g[3],nums[1]+nums[3]) //接着递推
4:两者中求最大
return max(f[n-1], g[n]);//两者中取最大返回
注意:因为两个数组的边界不同,所以返回的索引不同!