当前位置: 首页 > news >正文

代码随想录算法训练营第41天|LeetCode 121. 买卖股票的最佳时机、122.买卖股票的最佳时机II、123.买卖股票的最佳时机III

1. LeetCode 121. 买卖股票的最佳时机

题目链接:https://leetcode.cn/problems/best-time-to-buy-and-sell-stock/description/
文章链接:https://programmercarl.com/0121.买卖股票的最佳时机.html#思路
视频链接:https://www.bilibili.com/video/BV1Xe4y1u77q

在这里插入图片描述

思路:
1.确定dp数组(dp table)以及下标的含义。
dp[i][0] 表示第i天持有股票所得最多现金;
dp[i][1] 表示第i天不持有股票所得最多现金。
2.确定递推公式
1️⃣如果第i天持有股票即dp[i][0], 那么可以由两个状态推出来
第i-1天就持有股票,那么就保持现状,所得现金就是昨天持有股票的所得现金 即:dp[i - 1][0];
第i天买入股票,所得现金就是买入今天的股票后所得现金即:-prices[i]
那么dp[i][0]应该选所得现金最大的,所以dp[i][0] = max(dp[i - 1][0], -prices[i]);
2️⃣如果第i天不持有股票即dp[i][1], 也可以由两个状态推出来
第i-1天就不持有股票,那么就保持现状,所得现金就是昨天不持有股票的所得现金 即:dp[i - 1][1]
第i天卖出股票,所得现金就是按照今天股票价格卖出后所得现金即:prices[i] + dp[i - 1][0]
那么dp[i][1]取最大的,dp[i][1] = max(dp[i - 1][1], prices[i] + dp[i - 1][0]);
3.初始化
dp[0][0] -= prices[0];
dp[0][1] = 0;
4.遍历顺序
从前向后遍历。

解法:
class Solution {public int maxProfit(int[] prices) {if (prices.length==0 || prices.length==1) return 0;//1.定义dp数组 //dp[i][0]表示第i天持有股票金额//dp[i][1]表示第i天不持有股票金额int[][] dp = new int[prices.length][2];//2.递推公式//dp[i][0] = Math.max(dp[i-1][0],-prices[i]);//dp[i][1] = Math.max(dp[i-1][1],prices[i]+dp[i-1][0]);//3.初始化dp[0][0]=-prices[0];dp[0][1]=0;//4.遍历顺序for (int i=1;i<prices.length;i++) {dp[i][0] = Math.max(dp[i-1][0],-prices[i]);dp[i][1] = Math.max(dp[i-1][1],prices[i]+dp[i-1][0]);}return dp[prices.length-1][1];}
}

2. LeetCode 122.买卖股票的最佳时机II

题目链接:https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-ii/description/
文章链接:https://programmercarl.com/0122.买卖股票的最佳时机II(动态规划).html
视频链接:https://www.bilibili.com/video/BV1D24y1Q7Ls

在这里插入图片描述

思路:
本题和121. 买卖股票的最佳时机 (opens new window)的唯一区别是本题股票可以买卖多次了(注意只有一只股票,所以再次购买前要出售掉之前的股票)
递推公式:
1️⃣如果第i天持有股票即dp[i][0], 那么可以由两个状态推出来:
第i-1天就持有股票,那么就保持现状,所得现金就是昨天持有股票的所得现金 即:dp[i - 1][0]
第i天买入股票,所得现金就是昨天不持有股票的所得现金减去 今天的股票价格 即:dp[i - 1][1] - prices[i]
2️⃣如果第i天不持有股票即dp[i][1]的情况, 依然可以由两个状态推出来:
第i-1天就不持有股票,那么就保持现状,所得现金就是昨天不持有股票的所得现金 即:dp[i - 1][1]
第i天卖出股票,所得现金就是按照今天股票价格卖出后所得现金即:prices[i] + dp[i - 1][0]

class Solution {// // 贪心// public int maxProfit(int[] prices) {//     int res = 0;//     for (int i=1;i<prices.length;i++) {//         if (prices[i]-prices[i-1] > 0) {//             res += (prices[i]-prices[i-1]);//         }//     }//     return res;// }// //动态规划 1// public int maxProfit(int[] prices) {//     //1.定义dp数组//     //dp[i]表示第i天的最大利润//     int[] dp = new int[prices.length];//     //2.递推公式//     //dp[i]=Math.max(dp[i-1],dp[i-1]+(prices[i]-prices[i-1]));//     //3.初始化//     dp[0]=0;//     //4.遍历顺序//     for (int i=1;i<prices.length;i++) {//         dp[i]=Math.max(dp[i-1],dp[i-1]+(prices[i]-prices[i-1]));//     }//     return dp[prices.length-1];// }//动态规划 2public int maxProfit(int[] prices) {//1.定义dp数组//dp[i][0]表示第i天持有股票的金额//dp[i][1]表示第i天不持有股票的金额int[][] dp = new int[prices.length][2];//2.递推公式//dp[i][0]=Math.max(dp[i-1][0],dp[i-1][1]-prices[i]);//dp[i][1]=Math.max(dp[i-1][1],dp[i-1][0]+prices[i]);//3.初始化dp[0][0]=-prices[0];dp[0][1]=0;//4.遍历顺序for (int i=1;i<prices.length;i++) {dp[i][0]=Math.max(dp[i-1][0],dp[i-1][1]-prices[i]);dp[i][1]=Math.max(dp[i-1][1],dp[i-1][0]+prices[i]);}return dp[prices.length-1][1];}
}

3. LeetCode 123.买卖股票的最佳时机III

题目链接:https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-iii/description/
文章链接:https://programmercarl.com/0123.买卖股票的最佳时机III.html
视频链接:https://www.bilibili.com/video/BV1WG411K7AR

在这里插入图片描述

思路:
关键在于至多买卖两次,这意味着可以买卖一次,可以买卖两次,也可以不买卖。

1.确定dp数组以及下标的含义
一天一共就有五个状态:
0 没有操作 (其实我们也可以不设置这个状态)
1 第一次持有股票时的金额
2 第一次不持有股票时的金额
3 第二次持有股票时的金额
4 第二次不持有股票时的金额
dp[i][j]中 i表示第i天,j为 [0 - 4] 五个状态,dp[i][j]表示第i天状态j所剩最大现金。
2.确定递推公式
1️⃣dp[i][1]状态表示第i天第一次持有股票时的金额,有两个具体操作:
操作一:第i天买入股票了,那么dp[i][1] = - prices[i]
操作二:第i天没有操作,而是沿用前一天买入的状态,即:dp[i][1] = dp[i - 1][1]
选最大的,则递推公式为:dp[i][1] = max(-prices[i], dp[i - 1][1]);
2️⃣dp[i][2]状态表示第i天第一次不持有股票时的金额,有两个操作:
操作一:第i天卖出股票了,那么dp[i][2] = dp[i - 1][1] + prices[i]
操作二:第i天没有操作,沿用前一天卖出股票的状态,即:dp[i][2] = dp[i - 1][2]
选最大的,则递推公式为:p[i][2] = max(dp[i - 1][1] + prices[i], dp[i - 1][2]);
3️⃣dp[i][3]状态表示第i天第二次持有股票时的金额,有两个具体操作:
操作一:第i天买入股票了,那么dp[i][3] = dp[i-1][2] - prices[i]
操作二:第i天没有操作,而是沿用前一天买入的状态,即:dp[i][3] = dp[i - 1][3]
选最大的,则递推公式为:dp[i][3] = max(dp[i-1][2] - prices[i], dp[i - 1][3]);
4️⃣dp[i][4]状态表示第i天第二次不持有股票时的金额,有两个操作:
操作一:第i天卖出股票了,那么dp[i][4] = dp[i - 1][3] + prices[i]
操作二:第i天没有操作,沿用前一天卖出股票的状态,即:dp[i][4] = dp[i - 1][4]
选最大的,则递推公式为:p[i][4] = max(dp[i - 1][3] + prices[i], dp[i - 1][4]);
3.dp数组如何初始化
dp[0][0]=0;
dp[0][1]=-prices[0];
dp[0][2]=0;
dp[0][3]=-prices[0];
dp[0][4]=0;
4.确定遍历顺序
从递归公式其实已经可以看出,一定是从前向后遍历,因为dp[i],依靠dp[i - 1]的数值。

class Solution {public int maxProfit(int[] prices) {//1.定义dp数组//dp[i][0] 第i天没有操作//dp[i][1] 第i天第一次持有股票时的金额//dp[i][2] 第i天第一次不持有股票时的金额//dp[i][3] 第i天第二次持有股票时的金额//dp[i][4] 第i天第二次不持有股票时的金额int[][] dp = new int[prices.length][5];//2.递推公式//dp[i][1]=Math.max(dp[i-1][1],-prices[i]);//dp[i][2]=Math.max(dp[i-1][2],dp[i-1][1]+prices[i]);//dp[i][3]=Math.max(dp[i-1][3],dp[i-1][2]-prices[i]);//dp[i][4]=Math.max(dp[i-1][4],dp[i-1][3]+prices[i]);//3.初始化dp[0][0]=0;dp[0][1]=-prices[0];dp[0][2]=0;dp[0][3]=-prices[0];dp[0][4]=0;//4.遍历顺序 从前往后for (int i=1;i<prices.length;i++) {dp[i][1]=Math.max(dp[i-1][1],-prices[i]);dp[i][2]=Math.max(dp[i-1][2],dp[i-1][1]+prices[i]);dp[i][3]=Math.max(dp[i-1][3],dp[i-1][2]-prices[i]);dp[i][4]=Math.max(dp[i-1][4],dp[i-1][3]+prices[i]);}return dp[prices.length-1][4];}
}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 多进程编程思维导图
  • 06 定时器和PWM(1)
  • OD C卷 - 最多购买宝石数目
  • DBMS-1.2 关系运算
  • 使用Leaflet GeoMan结合天地图进行自由标绘实战
  • 备忘录模式
  • 使用GenAI做Discord舆情分析对游戏运营的帮助
  • 技术学习笔记 1:C++标准库异常类(c++中怎样用自己错误信息交给try catch捕获)
  • 餐饮连锁加盟的网页UI,如果不大气,谁能相信你的品牌力
  • Package.Json 参数配置理解用途
  • C:关于位操作符:、|、^、~的一些应用
  • 百日筑基第三十七天-阿里开发手册编程规约
  • 编程实践|如何用 MoonBit 实现 diff(三)
  • 使用css在照片右上角设置缎带效果
  • 请以零基础学Python 之 第二十讲 分组和贪婪匹配
  • JavaScript-如何实现克隆(clone)函数
  • android高仿小视频、应用锁、3种存储库、QQ小红点动画、仿支付宝图表等源码...
  • flutter的key在widget list的作用以及必要性
  • IE报vuex requires a Promise polyfill in this browser问题解决
  • Mysql5.6主从复制
  • MySQL数据库运维之数据恢复
  • python_bomb----数据类型总结
  • Vue2.0 实现互斥
  • 百度地图API标注+时间轴组件
  • 给Prometheus造假数据的方法
  • 规范化安全开发 KOA 手脚架
  • 近期前端发展计划
  • 你真的知道 == 和 equals 的区别吗?
  • 云大使推广中的常见热门问题
  • Python 之网络式编程
  • 长三角G60科创走廊智能驾驶产业联盟揭牌成立,近80家企业助力智能驾驶行业发展 ...
  • 回归生活:清理微信公众号
  • 说说我为什么看好Spring Cloud Alibaba
  • ​Java基础复习笔记 第16章:网络编程
  • ​猴子吃桃问题:每天都吃了前一天剩下的一半多一个。
  • ​你们这样子,耽误我的工作进度怎么办?
  • ​数据链路层——流量控制可靠传输机制 ​
  • #{}和${}的区别?
  • (21)起落架/可伸缩相机支架
  • (C语言)输入自定义个数的整数,打印出最大值和最小值
  • (html转换)StringEscapeUtils类的转义与反转义方法
  • (k8s)Kubernetes本地存储接入
  • (板子)A* astar算法,AcWing第k短路+八数码 带注释
  • (附源码)node.js知识分享网站 毕业设计 202038
  • (附源码)ssm高校社团管理系统 毕业设计 234162
  • (四)软件性能测试
  • (译) 理解 Elixir 中的宏 Macro, 第四部分:深入化
  • (最完美)小米手机6X的Usb调试模式在哪里打开的流程
  • *p=a是把a的值赋给p,p=a是把a的地址赋给p。
  • .[hudsonL@cock.li].mkp勒索病毒数据怎么处理|数据解密恢复
  • .htaccess 强制https 单独排除某个目录
  • .net core Swagger 过滤部分Api
  • .NET Micro Framework初体验
  • .Net Web窗口页属性
  • .NET 材料检测系统崩溃分析