动态规划DP(中上)(力扣中等难度题目解析)

不清楚动态规划是什么的同学先看看我的上一篇

双指针+动态规划(上)力扣解析_lihua777的博客-CSDN博客双指针+动态规划(上)力扣解析https://blog.csdn.net/lihua777/article/details/122650138?spm=1001.2014.3001.5501话不多说,我们直接上力扣题目解析:

目录

1:打家劫舍

 思路解析:

 2:打家劫舍||

 思路解析:

3:删除点数

 思路解析:

4:跳跃游戏(动态规划+贪心)

 思路解析:

5:跳跃游戏||

 思路解析:

第一种方法:暴力+从尾向头法:

第二种方法:动态规划+贪心

6:最大子组数和

 思路解析:

7:乘积最大子数组

 思路解析:

8:最佳观光组合

 思路解析:

9:买卖股票的最佳时机

 思路解析:

10:买卖股票的最佳时机||

 思路解析:

结语:


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]);//两者中取最大返回

注意:因为两个数组的边界不同,所以返回的索引不同!

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值