首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

动态规划LeetCode-123.买卖股票的最佳时机3

  • 25-03-08 01:40
  • 4268
  • 6217
blog.csdn.net

给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格。

设计一个算法来计算你所能获取的最大利润。你最多可以完成 两笔 交易。

注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

示例 1:

输入:prices = [3,3,5,0,0,3,1,4]
输出:6
解释:在第 4 天(股票价格 = 0)的时候买入,在第 6 天(股票价格 = 3)的时候卖出,这笔交易所能获得利润 = 3-0 = 3 。
     随后,在第 7 天(股票价格 = 1)的时候买入,在第 8 天 (股票价格 = 4)的时候卖出,这笔交易所能获得利润 = 4-1 = 3 。

示例 2:

输入:prices = [1,2,3,4,5]
输出:4
解释:在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。   
     注意你不能在第 1 天和第 2 天接连购买股票,之后再将它们卖出。   
     因为这样属于同时参与了多笔交易,你必须在再次购买前出售掉之前的股票。

示例 3:

输入:prices = [7,6,4,3,1] 
输出:0 
解释:在这个情况下, 没有交易完成, 所以最大利润为 0。

示例 4:

输入:prices = [1]
输出:0

提示:

  • 1 <= prices.length <= 10^5
  • 0 <= prices[i] <= 10^5

 这题是个系列题,我们得从买卖股票的最佳时机1开始做起,从1开始做所定义的dp含义都是相似的。不懂写买卖股票的最佳时机1和2的小伙伴,可以看我的分享的博客。
动态规划LeetCode-121.买卖股票的最佳时机1-CSDN博客
动态规划LeetCode-122.买卖股票的最佳时机2-CSDN博客

那我们现在开始看一下这三个有什么区别。买卖股票的最佳时机1是只可以买卖一次,2是可以买卖无限次,而3是只可以买卖至多两次。之前的1和2的dp含义dp[i][0] 表示第i天持有股票时的最大现金,dp[i][1] 表示第i天不持有股票时的最大现金,我们记录每天持有和不持有的最大现金,慢慢推导到最后就可以得出卖出得到的最大现金。
那现在买卖股票的最佳时机3说至多2次,那我们就得细分状态。一天就五个状态,无操作、第一次买入、第一次卖出、第二次买入、第二次卖出,我们在每天分别记录进行这些操作手上所得到的最大现金

所以我们就得出dp含义:
dp[i][0]:表示第i天无操作得到手上最大现金。
dp[i][1]:表示第i天第一次持有股票时手上的最大现金。
dp[i][2]:表示第i天第一次不持有股票时手上的最大现金。
dp[i][3]:表示第i天第二次持有股票时手上的最大现金。
dp[i][4]:表示第i天第二次不持有股票时手上的最大现金。

注意,我们依旧解释一下持有和不持有,持有和不持有不一定是真正的买入,我们只是记录记录!也可以这么理解一下,比如dp[i][1],第i天,如果(注意是如果)这时候进行第一次买入,那我们手上的最大现金是多少,每天都进行比较和记录最值,第i天如果进行第一次买入股票,这时手上的最大现金是多少,一直记录着最值慢慢推导到最后,所以dp[pricesSize-1][1]所得到的值就是真正的第一次买入股票时手上的最大现金。因为是第一次买入,最后的dp[pricesSize-1][1]的dp值就是真正第一次买入股票时股票的价格,真正第一次买入的时候是在股票最低价格的时候买,dp对应的就是手上的最大现金。我们每天都把这些操作记录下来,相当于是第i天如果进行某个操作手上的最大现金,每次都保存符合题意的最值,一直记录并推导到最后就得出结果。

所以我们看一下递推公式:
dp[i][0]:无操作的话我们初始化第0天之后,以后的第i天dp[i][0]延续第i-1天的dp[i-1][0]。dp[i][0] = dp[i-1][0];

dp[i][1]:还未进行第一次买入的时候,我们手上的现金为0,那如果我们要是进行第一次买入,那就是无操作所得的最大现金dp[i][0]减去prices[i]得到第i天第一次持有股票时手上的最大现金,这个与第i-1天的dp[i][1]进行比较取最大值,每天记录保存的是第一次持有股票时手上的最大现金。 dp[i][1] = dp[i-1][1] > dp[i-1][0] - prices[i] ? dp[i-1][1] : dp[i-1][0] - prices[i];

dp[i][2]:第一次不持有的话肯定是在第一次持有的情况下进行的,所以就是第一次持有股票的最大现金加上prices[i](当前不持有则是卖出,那就是获得当前价格的金额)。 dp[i][2] = dp[i-1][2] > dp[i-1][1] + prices[i] ? dp[i-1][2] : dp[i-1][1] + prices[i];

dp[i][3]:同理,第二次持有是在第一次不持有的情况下进行的,所以就是第一 不持有股票时的最大现金减去prices[i](持有的话就是买入了,那手上最大现金就是减去prices[i],但不是真正的买入,只是一个如果并记录)。dp[i][3] = dp[i-1][3] > dp[i-1][2] - prices[i] ?dp[i-1][3] : dp[i-1][2] - prices[i];

dp[i][4]:同理,dp[i][4] = dp[i-1][4] > dp[i-1][3] + prices[i] ? dp[i-1][4] : dp[i-1][3] + prices[i];

初始化:
dp[i][0]:第0天,不进行操作,手上最大现金就是0,所以dp[0][0] = 0;

dp[i][1]:第0天,如果进行第一次持有(买入但并不是真正的买入),手上的最大现金就是0-prices[0],所以dp[0][1] = 0-prices[0];

dp[i][2]:第0天,如果进行第一次不持有,手上的最大现金就是0 - prices[0] + prices[0]=0,所以dp[0][2] = 0;

dp[i][3]:第0天,如果进行第二次持有,手上的最大现金就是0 - prices[0] + prices[0] - prices[0]= 0-prices[0],所以dp[0][3] = 0-prices[0];

dp[i][4]:第0天,如果进行第二次不持有,手上的最大现金就是0 - prices[0] + prices[0] - prices[0] + prices[0] = 0,所以dp[0][4] = 0;

遍历顺序:从前往后

打印数组:当遇到疑惑或者提交错误时,打印数组出来比较快速的看看哪一步有错。


以下是我在力扣c语言提交的代码,仅供参考:

  1. int maxProfit(int* prices, int pricesSize) {
  2. //五个操作
  3. int dp[pricesSize][5];
  4. //初始化
  5. dp[0][0] = 0;
  6. dp[0][1] = 0-prices[0];
  7. dp[0][2] = 0;
  8. dp[0][3] = 0-prices[0];
  9. dp[0][4] = 0;
  10. for(int i = 1;i<pricesSize;i++)
  11. {
  12. dp[i][0] = dp[i-1][0];
  13. // 第一次持有:保持现状(第i-1天的结果)或当天买入
  14. dp[i][1] = dp[i-1][1] > dp[i-1][0] - prices[i] ? dp[i-1][1] : dp[i-1][0] - prices[i];
  15. // 第一次不持有:保持现状(第i-1天的结果)或当天卖出
  16. dp[i][2] = dp[i-1][2] > dp[i-1][1] + prices[i] ? dp[i-1][2] : dp[i-1][1] + prices[i];
  17. // 第二次持有:保持现状(第i-1天的结果)或第一次卖出后买入
  18. dp[i][3] = dp[i-1][3] > dp[i-1][2] - prices[i] ?dp[i-1][3] : dp[i-1][2] - prices[i];
  19. 第二次不持有:保持现状(第i-1天的结果)或第二次买入后卖出
  20. dp[i][4] = dp[i-1][4] > dp[i-1][3] + prices[i] ? dp[i-1][4] : dp[i-1][3] + prices[i];
  21. }
  22. return dp[pricesSize-1][4];
  23. }

 

 

注:本文转载自blog.csdn.net的欧了111的文章"https://blog.csdn.net/2303_80070412/article/details/145484665"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

137
数学
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2024 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top