上来直接最难的,后面都是毛毛雨

问题一:买卖股票的最佳时机IV(leetcode188)

问题二:最大可交易次数不限(leetcode122)

问题三:最大交易次数为1(leetcode121)

问题四:最大交易次数为2(leetcode123)

问题五:买卖股票最佳时间含手续费(leetcode714)

问题六:最佳股票买卖时机含冷冻期(leetcode309)


问题一:买卖股票的最佳时机IV(leetcode188)

问题描述:

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

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

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-iv
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

大体思路:

二维数组dp0[i][j]表示在第i天,最大可交易次数为j时不持有股票的最大收益;

同理dp1[i][j]表示在第天,最大可交易次数为j时持有股票的最大收益。i从0到最大天数,j从0到k。

dp0[i][j] = max(dp0[i - 1][j], dp1[i - 1][j] + prices[i])

dp1[i][j] = max(dp1[i - 1][j], dp0[i - 1][j - 1] - prices[i])

第一个式子:当天没有股票有两种可能,要么前一天就没持有股票;要么为前一天持有股票,当天卖了。

第二个式子:当天持有股票有两种可能,要么前一天就持有股票,或者前一天没持有股票,当天买入了。

注:这里需要注意的是第二个式子中,第二种情况下的前一天的最大可交易次数为j-1而不为j,这是由于买入的次数要小于最大买入次数,假设为dp0[i - 1][j] 他可能在i-1天之前已经进行过j次交易了,在第i天坑定不能再买入了。

传递函数有了,下面描述其的初值。

我们从传递函数发现,当前值总是与其正上方的值和左上角的值有关,因此只要对dp0和dp1的第一列第一行初始化即可。

dp0的第一列和第一行均为0,首先第一列j=0,由于最大可交易次数为0,那坑定不能买了为0,第一行i= 0,由于在第1天,不持有股票只有一种可能就是没有买所以为0。

dp1的第一列,j= 0最大可交易次数为0,但是还要持有,这是不可能实现的,因此为非法状态统统设为负无穷;第一行(除第一个元素)i = 0,可交易次数大于0了,在第1天想持有股票,只能买第一天的,因此统统设为 -1 * prices[0]。

实现代码如下:

class Solution {public int maxProfit(int k, int[] prices) {if(k == 0 || prices.length <= 1){return 0;}if(k > prices.length / 2){return maxProfit(prices);}int[][] dp0 = new int[prices.length][k + 1];int[][] dp1 = new int[prices.length][k + 1];/* dp0[i][0] 和 dp0[0][j] 均为0*/for(int i = 0; i < prices.length; i++){dp1[i][0] = Integer.MIN_VALUE;}for(int j = 1; j < k + 1; j++){dp1[0][j] = -1 * prices[0];}for(int i = 1; i < prices.length; i++){for(int j = 1; j < k + 1; j++){dp0[i][j] = Math.max(dp0[i - 1][j], dp1[i - 1][j] + prices[i]);dp1[i][j] = Math.max(dp1[i - 1][j], dp0[i - 1][j - 1] - prices[i]);}}return dp0[prices.length - 1][k];}public int maxProfit(int[] prices) {if(prices.length <= 1){return 0;}int[] dp0 = new int[prices.length];int[] dp1 = new int[prices.length];dp1[0] = -1 * prices[0];for(int i = 1; i < dp0.length; i++){dp0[i] = Math.max(dp0[i - 1], dp1[i - 1] + prices[i]);dp1[i] = Math.max(dp1[i - 1], dp0[i - 1] - prices[i]);}return dp0[dp0.length - 1];}
}

由于k可能很大,当k > n / 2时问题就会转化为不用考虑最大交易次数的情况,可以认为最大交易次数为无穷。后面的代码下一节将会分析。

问题二:最大可交易次数不限(leetcode122)

该问题是问题一中k = 无穷的特例,此时 k = k - 1,因此转移函数变为

dp0[i] = max(dp0[i - 1], dp1[i - 1] + prices[i])

dp1[i] = max(dp1[i - 1], dp0[i - 1] - prices[i])

问题由二维dp转化为一维dp

初值为:d0[0] = 0,没买肯定是0啊, d1[0] = -prices[0],买了肯定是- prices[0]。

实现代码如下:

    public int maxProfit(int[] prices) {if(prices.length <= 1){return 0;}int[] dp0 = new int[prices.length];int[] dp1 = new int[prices.length];dp1[0] = -1 * prices[0];for(int i = 1; i < dp0.length; i++){dp0[i] = Math.max(dp0[i - 1], dp1[i - 1] + prices[i]);dp1[i] = Math.max(dp1[i - 1], dp0[i - 1] - prices[i]);}return dp0[dp0.length - 1];}

问题三:最大交易次数为1(leetcode121)

dp0[i][j] = max(dp0[i - 1][j], dp1[i - 1][j] + prices[i])

dp1[i][j] = max(dp1[i - 1][j], dp0[i - 1][j - 1] - prices[i])

将上式中的j换成1,得到如下:

dp0[i][1] = max(dp0[i - 1][1], dp1[i - 1][1] + prices[i])

dp1[i][1] = max(dp1[i - 1][1], dp0[i - 1][0] - prices[i])

由于dp0[i - 1][0] = 0,所以最终化简后的转移方程为:

dp0[i]= max(dp0[i - 1], dp1[i - 1]+ prices[i])

dp1[i]= max(dp1[i - 1], 0 - prices[i])

初值:dp0[0] = 0, dp1[0] = -prices[0]

该结果也可以使用自然语言理解,当天不持有的有两种情况,或者前一天就不持有,或者前一天持有当天卖出去了;当天持有的两种情况为:前一天就持有,或者前一天不会持有,当天买了。由于只能买一次,前一天不持有说明之前也没进行过交易,因此前一天不持有的最大收益为0.

实现代码如下:

    public int maxProfit(int[] prices) {if(prices.length <= 1){return 0;}int[] dp0 = new int[prices.length];//  dp0[i] i天不持有股票的最大利润int[] dp1 = new int[prices.length]; // 持有股票的最大利润 dp0[0] = 0;dp1[0] = -1 * prices[0];for(int i = 1; i < prices.length; i++){dp0[i] = Math.max(dp0[i - 1], dp1[i - 1] + prices[i]);dp1[i] = Math.max(dp1[i - 1], 0 - prices[i]);}return dp0[dp0.length - 1];}

当然由于只交易一次,因此还可以很多其他办法解决,比如可以使用贪心的策略,找到当前点之前最小的元素,即在前面那个位置买,在当前点卖。由于本文主要将dp,这里就不多加赘述了。

问题四:最大交易次数为2(leetcode123)

这问题没啥说的,就令k=2咯,直接搞。

代码如下:

    public int maxProfit(int[] prices) {if(prices.length <= 1){return 0;}int K = 2;int[][] dp0 = new int[prices.length][K + 1];int[][] dp1 = new int[prices.length][K + 1]; // dp0[0][k] 和 dp0[i][0] 均为0for(int i = 0; i < prices.length; i++){ // 第一列 最大允许交易次数为0 还要持有 定为非法dp1[i][0] = Integer.MIN_VALUE;}for(int k = 1; k <= K; k++){ //第一行dp1[0][k] = -1 * prices[0];}for(int i = 1; i < prices.length; i++){for(int k = 1; k <= K; k++){dp0[i][k] = Math.max(dp0[i - 1][k], dp1[i - 1][k] + prices[i]);dp1[i][k] = Math.max(dp1[i - 1][k], dp0[i - 1][k - 1] - prices[i]);}}return dp0[prices.length - 1][K];}

问题五:买卖股票最佳时间含手续费(leetcode714)

问题描述:

给定一个整数数组 prices,其中第 i 个元素代表了第 i 天的股票价格 ;非负整数 fee 代表了交易股票的手续费用。

你可以无限次地完成交易,但是你每笔交易都需要付手续费。如果你已经购买了一个股票,在卖出它之前你就不能再继续购买股票了。

返回获得利润的最大值。

注意:这里的一笔交易指买入持有并卖出股票的整个过程,每笔交易你只需要为支付一次手续费。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-with-transaction-fee
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

大体思路:

直接在k=无穷上改就行,由于每笔交易都含手续费,因此在卖的时候加上手续费就行,转移方程如下:

dp0[i] = max(dp0[i - 1], dp1[i - 1] + prices[i] - fee)

dp1[i] = max(dp1[i - 1], dp0[i - 1] - prices[i])

初值 dp0[0] = 0, dp1[0] = - prices[0]

代码如下:

    public int maxProfit(int[] prices, int fee) {if(prices.length <= 1){return 0;}int[] dp0 = new int[prices.length];int[] dp1 = new int[prices.length];dp1[0] = -1 * prices[0];for(int i = 1; i < prices.length; i++){dp0[i] = Math.max(dp0[i - 1], dp1[i - 1] + prices[i] - fee);dp1[i] = Math.max(dp1[i - 1], dp0[i - 1] - prices[i]);}return dp0[dp0.length - 1];}

问题六:最佳股票买卖时机含冷冻期(leetcode309)

问题描述:

给定一个整数数组,其中第 i 个元素代表了第 i 天的股票价格 。​

设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票):

你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。
示例:

输入: [1,2,3,0,2]
输出: 3 
解释: 对应的交易状态为: [买入, 卖出, 冷冻期, 买入, 卖出]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-with-cooldown
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

大体思路:

由于当天卖出股票后第二天不能直接买入,也就是说只有前天没持有,昨天没持有,今天才可以进行买入。传递函数如下:

dp0[i] = max(dp0[i - 1], dp1[i - 1] + prices[i])

dp1[i] = max(dp1[i - 1], dp0[i - 2] - prices[i])

由于前天没有持有,昨天也没有持有,今天买入之前的收益是等于前天的收益的。因此为dp0[i - 2] - prices[i]

由于用到i- 2,初值除了赋i= 0,还应对 i = 1赋值。

dp0[0] = 0;

dp1[0] = 0 - prices[0];

dp0[1] = Math.max(dp0[0], dp1[0] + prices[1]);

dp1[1] = Math.max(dp1[0], dp0[0] - prices[1]);// 由于-1时坑定没卖出,因此为dp0[0] - prices[1]。

实现代码如下:

    public int maxProfit(int[] prices) {// return dfs(prices, 0, 0, 0, 0);if(prices.length <= 1){return 0;}int[] dp0 = new int[prices.length]; //dp0[i] 为i天不持有股票的最大收益int[] dp1 = new int[prices.length]; //dp0[0] = 0;dp1[0] = 0 - prices[0];dp0[1] = Math.max(dp0[0], dp1[0] + prices[1]);dp1[1] = Math.max(dp1[0], dp0[0] - prices[1]);for(int i = 2; i < prices.length; i++){dp0[i] = Math.max(dp0[i - 1], dp1[i - 1] + prices[i]);dp1[i] = Math.max(dp1[i - 1], dp0[i - 2] - prices[i]);}return dp0[prices.length - 1];}

股票交易问题全拿下,一扫光相关推荐

  1. 看完946页“JAVA高级架构面试必问”,金九银十社招全拿下

    前言 我本科毕业后在老东家干了两年多,老东家算是一家"小公司"(毕竟这年头没有 BAT 或 TMD 的 title 都不好意思报出身),毕业这两年多我也没有在大厂待过,因此找坑的时 ...

  2. 946页“JAVA高级架构必问面试精华”,金九银十社招全拿下

    前言 我本科毕业后在老东家干了两年多,老东家算是一家"小公司"(毕竟这年头没有 BAT 或 TMD 的 title 都不好意思报出身),毕业这两年多我也没有在大厂待过,因此找坑的时 ...

  3. 清华朱军团队开源UniDiffuser:首个基于Transformer的多模态扩散大模型!文图互生、改写全拿下!...

    点击下方卡片,关注"CVer"公众号 AI/CV重磅干货,第一时间送达 点击进入->[多模态和扩散模型]微信技术交流群 转载自:机器之心 该论文提出了一个为多 模态设计的概率 ...

  4. 老牌名校助理教授给出8个建议

    点击上方"视学算法",选择加"星标"或"置顶" 重磅干货,第一时间送达 作者丨子豪 来源丨量子位 编辑丨极市平台 学术写作,绝对算得上高校学 ...

  5. 热门专业没那么难,文科生打开统计学的正确方式!

    六月,初夏. 高考结束,毕业季到来.准大学生纠结选什么专业,毕业生迈进就业大军,不论什么身份,大家都在思考着同一件事情--当下什么能力最热门? 想要得到答案很简单,打开任意一款求职软件,热门岗位的职位 ...

  6. 简单点,让论文写作简单点,老牌名校助理教授给出8个建议

    子豪 发自 凹非寺 量子位 报道 | 公众号 QbitAI 学术写作,绝对算得上高校学生最为头痛的事之一,无论是论文,还是研究报告.说明文件-- 对理工科学生来说,更是难上加难--方案.实验全拿下,一 ...

  7. 辣眼睛:程序员这样过儿童节

    需要智慧 戏精程序员 不能浪得虚名 "我觉得这个不错,宅男都爱,兄弟,你的公仔借我们一用." "这东西你哪里淘来的?不愧是震桌之宝" 搜刮了整栋大楼之后 阿里云 ...

  8. 高盛发布区块链报告:从理论到实践(中文版)

    投资组合经理之摘要 现在硅谷和华尔街都为了区块链着迷,逐渐忘记了作为其技术源头的比特币.但对其潜在应用的讨论仍十分抽象和深奥.焦点在于使用分布式账本建立去中心化市场,并削弱现有中间商的控制权. 但区块 ...

  9. 前端面试——初(H)入(T)江(M)湖(L)

    前言 如果觉得文章对您有帮助记得给个 Star,你的 star 是我动力的源泉.github 地址 正所谓面试如考试,考试如战场.战场上必将刀光剑影. 阅文档,刷试题,只求简历能入围 会面试官,戏 H ...

最新文章

  1. 高级特性(4)- 数据库编程
  2. linux kernel 2.6.36 编译升级
  3. 最长回文子串python_最长回文子串(Python)
  4. 被关起来日子的流水帐
  5. 熊猫的python小课账号_学习python中的pandas有没有好的教程推荐?
  6. 线性代数:矩阵乘向量-学习笔记
  7. iPhone 13临近发布,富士康需要在9月底前再招聘20万名工人
  8. [AST实战]从零开始写一个wepy转VUE的工具
  9. Kibana将语言设置为中文
  10. 读 疯狂的程序员 有感
  11. PD快充协议JD6606S资料
  12. 如果矩阵中存在字符用C语言,面试中常见的数据结构与算法题整理,想当架构师,数据结构与算法不过关可不行(数组+字符串,共60题)...
  13. call方法 java_漫谈JS中的call和apply方法
  14. 相见恨晚的5个资源网站 影视音乐资源随你看
  15. 数字化转型对企业的意义
  16. linux请求超时 ping_linux下ping命令使用详解
  17. java字符串同构_Java同构代码
  18. 每日一录20220816—01
  19. 如何从WinXP镜像中提取超级终端程序?
  20. 导航装备便携式综合测试工装

热门文章

  1. 内核调试番外篇 - KDB的介绍与简单使用
  2. MAC上使用密钥登录腾讯云轻量级服务器 保存连接信息 一键登录 保姆级教程
  3. 炫美泡泡飞舞特效(源代码+效果)
  4. table合并单元格
  5. 佳能C3025打印机扫描方法
  6. JavaScript Boolean(布尔)对象
  7. 【20211114】在技术上是如何实现分布式事务_V4(本地消息可靠消息)
  8. Android原生编解码接口 MediaCodec 之——完全解析
  9. GNS3导入Cisco PIX防火墙镜像步骤
  10. PCB生产工艺流程一:PCB分类的三大要点