目录

  • 121. 买卖股票的最佳时机
    • 贪心
    • dp思路
    • 滚动数组优化
  • 122. 买卖股票的最佳时机 II
  • 123. 买卖股票的最佳时机 III
  • 188. 买卖股票的最佳时机 IV
  • 309. 最佳买卖股票时机含冷冻期
  • 714. 买卖股票的最佳时机含手续费

121. 买卖股票的最佳时机

贪心

取最左最小值,取最右最大值,差值为最大利润

class Solution {public:int maxProfit(vector<int>& prices) {int n = prices.size();int minprice = prices[0];int maxpro = 0;for(int i = 1; i < n; i++){minprice = min(prices[i],minprice);maxpro = max(prices[i]-minprice,maxpro);}return maxpro;}
};

dp思路

step1:dp[i][0]表示第i天持有股票最大所得现金。本题中只能买卖一次,所以买入后金额为-price[i]
dp[i][1]表示第i天不持有股票最大所得现金。持有不等同于买入。
step2:
如果第i天持有股票dp[i][0]可以由两个状态得到。
case1:第i-1持有股票,保持现状,dp[i][0] = dp[i-1][0]
case2:第i天买入股票,所得现金就是买入今天的股票后所得现金。即dp[i][0] = -price[i]
dp[i][0] = max(dp[i-1][0],-price[i]);
如果第i天不持有股票dp[i][1]可以由两个状态得到。
case1: 第i-1不持有股票,保持现状,dp[i][1] = dp[i-1][1]
case2: 第i-1持有股票,第i天卖出,dp[i][1] = dp[i-1][0] + price[i]
dp[i][1] = max(dp[i-1][1],dp[i-1][0]+price[i])
step3:
初始状态为dp[0][0]:第0天持有股票的金额 = -prices[0]
dp[0][1]第0天不持有股票的金额 = 0;
最终结果dp[n][1]而不是dp[n][0],是因为最终必须要把股票卖出才能有收益。不卖出一定更亏。

class Solution {public:int maxProfit(vector<int>& prices) {int n = prices.size();vector<vector<int>> dp(n,vector<int>(2,0));dp[0][0] = -prices[0];dp[0][1] = 0;for(int i = 1; i < n; i++){//持有dp[i][0] = max(dp[i-1][0],-prices[i]);//不持有dp[i][1] = max(dp[i-1][1],dp[i-1][0]+prices[i]);}return dp[n-1][1];}
};

滚动数组优化

由于只用到了dp[i] 与dp[i-1]两个状态,所以只需一个2 * 2的数组即可。

class Solution {public:int maxProfit(vector<int>& prices) {int n = prices.size();vector<vector<int>> dp(2,vector<int>(2,0));dp[0][0] = -prices[0];dp[0][1] = 0;for(int i = 1; i < n; i++){//持有dp[i % 2][0] = max(dp[(i-1)%2][0],-prices[i]);//不持有dp[i % 2][1] = max(dp[(i-1)%2][1],dp[(i-1)%2][0]+prices[i]);}return dp[(n-1)%2][1];}
};

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

dp[i][0]:第i天持有股票获取的最大现金
dp[i][1]:第i天不持有股票所得的最多现金
如果第i天持有股票,则dp[i][0]可以由两个状态推导;
case1:第i-1天就持有股票,保持现状,则dp[i][0] = dp[i-1][0]
case2:第i天买入股票,现金则为昨天不持有股票所得现金减去今天股票价格dp[i][0] = dp[i-1][1] - prices[i]
如果第i天不持有股票,则dp[i][1]可以由两个状态推导;
case1:第i-1天不持有股票,保持现状,dp[i][1] = dp[i-1][1]
case2:第i-1天持有股票,第i天卖出,dp[i][1] = dp[i-1][0] + prices[i]

class Solution {public:int maxProfit(vector<int>& prices) {int n = prices.size();vector<vector<int>> dp(2,vector<int>(2,0));dp[0][0] = -prices[0];dp[0][1] = 0;for(int i = 1; i < n; i++){dp[i%2][0] = max(dp[(i-1)%2][0],dp[(i-1)%2][1]-prices[i]);dp[i%2][1] = max(dp[(i-1)%2][1],dp[(i-1)%2][0]+prices[i]);}return dp[(n-1)%2][1];}
};

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

至多买卖两次,即可以买卖一次,也可以买卖两次,也可以不买卖。
每一天由五个状态:
0、没有操作
1、第一次买入
2、第一次卖出
3、第二次买入
4、第二次卖出
dp[i][j]:i表示第i天,j为[0-4]五个状态,dp[i][j]表示第i天状态j所剩最大现金。

2、确定递推公式
举例dp[i][1]:表示第i天,买入股票的状态,并不是说一定要第i天买入股票。
达到dp[i][1]状态,有两个具体操作:
case1:第i天买入股票,那么dp[i][1] = dp[i-1][0] - prices[i]
case2:第i天没有操作,那么dp[i][1] = dp[i-1][1]
dp[i-1][1] = max(dp[i-1][0]-prices[i],dp[i-1][1]);
同理dp[i][2]也有两个操作:
case1:第i天卖出股票了,那么dp[i][2] = dp[i-1][1] + prices[i]
case2:第i天没有操作,沿用前一天卖出股票的状态,即:dp[i][2] = dp[i-1][2]
所以dp[i][2] = max(dp[i-1][1] + prices[i],dp[i-1][2])
同理dp[i][3]也有两个操作:
case1:第i天买入股票,dp[i][3] = dp[i-1][2] - prices[i]
case2:第i天没有操作,沿用前一天买入股票的状态,即:dp[i][3] = dp[i-1][3]
同理dp[i][4]也有两个操作:
case1:第i天卖出股票,dp[i][4] = dp[i-1][3] + prices[i]
case2:第i天没有操作,沿用前一天卖出股票的状态,即:dp[i][4] = dp[i-1][4]
那么如何初始化呢?
第0天没有操作的话,dp[0][0] = 0
第0天做第一次买入操作的话,dp[0][1] = -prices[0]
第0天做第一次卖出的操作,这个初始值为0。
第0天第二次买入,不管几次,手头上没有钱,只能减少dp[0][3] = -prices[0]
第0天第二次卖出,dp[0][4] = 0

class Solution {public:int maxProfit(vector<int>& prices) {int n = prices.size();vector<vector<int>> dp(n,vector<int>(5,0));//dp[0][0] = 0;dp[0][1] = -prices[0];//dp[0][2] = 0;dp[0][3] = -prices[0];//dp[0][4] = 0;for(int i = 1; i < n; i++){dp[i][0] = dp[i-1][0];dp[i][1] = max(dp[i-1][1],dp[i-1][0]-prices[i]);dp[i][2] = max(dp[i-1][2],dp[i-1][1]+prices[i]);dp[i][3] = max(dp[i-1][3],dp[i-1][2]-prices[i]);dp[i][4] = max(dp[i-1][4],dp[i-1][3]+prices[i]);}return dp[n-1][4];}
};

188. 买卖股票的最佳时机 IV

step1:
这一题为上一题的进阶版本,定义二维dp数组。
使用二维数组dp[i][j]:第i天的状态为j,所剩下的最大现金是dp[i][j]
j的状态表示为:
0不操作、1第一次买入、2第一次卖出、…
除了0以外,偶数就是卖出,奇数就是买入。因为是最多有k笔交易,所以j的范围就定义为2*k+1.

vector<vector<int>> dp(prices.size(),vector<int>(2*k+1,0));

step2:

for(int j = 0; j < 2 * k - 1; j+=2)
{//奇数,说明买入dp[i][j+1] = max(dp[i-1][j+1],dp[i-1][j] - prices[i]);//偶数,说明卖出dp[i][j+2] = max(dp[i-1][j+2],dp[i-1][j+1] + prices[i]);
}

step3:
初始化,只要是买入操作,现金就会相应减少,卖出操作初值均为0

for(int j = 1; j < 2*k; j += 2)
{dp[0][j] = -prices[0];
}

AC代码:

class Solution {public:int maxProfit(int k, vector<int>& prices) {int n = prices.size();if(n == 0 || k == 0) return 0; vector<vector<int>> dp(n,vector<int>(k*2+1,0));for(int i = 1; i <= 2*k; i += 2)dp[0][i] = -prices[0];for(int i = 1; i < n; i++){for(int j = 0; j <= 2 * k - 2; j += 2){dp[i][j+1] = max(dp[i-1][j+1],dp[i-1][j]-prices[i]);dp[i][j+2] = max(dp[i-1][j+2],dp[i-1][j+1]+prices[i]);}}return dp[n-1][2*k];}
};

309. 最佳买卖股票时机含冷冻期

状态一:买入股票状态(可能是今天买入的,也有可能是之前就买入了然后没有操作)
对于卖出股票状态,有两种:
状态二:两天前就卖出了股票,度过了冷冻期,然后一直没有操作,今天仍然保持卖出股票状态
状态三:今天卖出了股票
状态四:今天为冷冻期状态,但冷冻期状态不可持续,只有一天
递推公式如下:
到达买入股票状态(状态一)即dp[i][0],有两个具体操作:
case1:前一天就是这个状态,今天沿用该状态dp[i][0] = dp[i-1][0]
case2:今天买入,有两种情况(状态四)
前一天是冷冻期,前一天是保持卖出股票的状态(状态二),这两个情况今天都有可能买入
即:dp[i][0] = max(dp[i-1][0],max(dp[i-1][3],dp[i-1][1])-prices[i])
到达保持卖出状态(状态二)即:dp[i][1],有两个具体操作:
case1:前一天就是状态二,沿用该状态
case2:前一天是冷冻期(状态四)
dp[i][1] = max(dp[i-1][1],dp[i-1][3])
到达今天卖出股票状态(状态三),只有一个状态,前一天是状态一,然后今天卖出
dp[i][2] = dp[i-1][0] + prices[i]
到达冷冻期状态(状态四),只有一个状态,前一天刚卖出股票
dp[i][3] = dp[i-1][2]
综上的递推代码为:

dp[i][0] = max(dp[i-1][0],max(dp[i-1][3],dp[i-1][1])-prices[i]);
dp[i][1] = max(dp[i-1][1],dp[i-1][3]);
dp[i][2] = dp[i-1][0] + prices[i];
dp[i][3] = dp[i-1][2];

关于dp数组的初始化:
状态一,持有股票,那么dp[0][0] = -prices[0]
状态二,保持卖出状态,dp[0][1] = 0
状态三,刚卖出股票,同样不会有收入dp[0][2] = 0
状态四,冷冻期,dp[0][3] = 0
最后的结果是从状态二到状态四中选取最大值。

class Solution {public:int maxProfit(vector<int>& prices) {int n = prices.size();vector<vector<int>> dp(n,vector<int>(4,0));dp[0][0] = -prices[0];for(int i = 1; i < n; i++){dp[i][0] = max(dp[i-1][0],max(dp[i-1][1],dp[i-1][3])-prices[i]);dp[i][1] = max(dp[i-1][1],dp[i-1][3]);dp[i][2] = dp[i-1][0] + prices[i];dp[i][3] = dp[i-1][2];}return max(dp[n-1][1],max(dp[n-1][2],dp[n-1][3]));}
};

714. 买卖股票的最佳时机含手续费

与122. 买卖股票的最佳时机 II相比,多减去操作费用。

class Solution {public:int maxProfit(vector<int>& prices, int fee) {int n = prices.size();vector<vector<int>> dp(2,vector<int>(2,0));dp[0][0] = -prices[0];dp[0][1] = 0;for(int i = 1; i < n; i++){//当天持有dp[i%2][0] = max(dp[(i-1)%2][0],dp[(i-1)%2][1]-prices[i]);//当天不持有dp[i%2][1] = max(dp[(i-1)%2][1],dp[(i-1)%2][0]+prices[i]-fee);}return dp[(n-1)%2][1];}
};

《dp补卡——买卖股票问题》相关推荐

  1. ComeFuture英伽学院——2020年 全国大学生英语竞赛【C类初赛真题解析】(持续更新)

    视频:ComeFuture英伽学院--2019年 全国大学生英语竞赛[C类初赛真题解析]大小作文--详细解析 课件:[课件]2019年大学生英语竞赛C类初赛.pdf 视频:2020年全国大学生英语竞赛 ...

  2. ComeFuture英伽学院——2019年 全国大学生英语竞赛【C类初赛真题解析】大小作文——详细解析

    视频:ComeFuture英伽学院--2019年 全国大学生英语竞赛[C类初赛真题解析]大小作文--详细解析 课件:[课件]2019年大学生英语竞赛C类初赛.pdf 视频:2020年全国大学生英语竞赛 ...

  3. 信息学奥赛真题解析(玩具谜题)

    玩具谜题(2016年信息学奥赛提高组真题) 题目描述 小南有一套可爱的玩具小人, 它们各有不同的职业.有一天, 这些玩具小人把小南的眼镜藏了起来.小南发现玩具小人们围成了一个圈,它们有的面朝圈内,有的 ...

  4. 信息学奥赛之初赛 第1轮 讲解(01-08课)

    信息学奥赛之初赛讲解 01 计算机概述 系统基本结构 信息学奥赛之初赛讲解 01 计算机概述 系统基本结构_哔哩哔哩_bilibili 信息学奥赛之初赛讲解 02 软件系统 计算机语言 进制转换 信息 ...

  5. 信息学奥赛一本通习题答案(五)

    最近在给小学生做C++的入门培训,用的教程是信息学奥赛一本通,刷题网址 http://ybt.ssoier.cn:8088/index.php 现将部分习题的答案放在博客上,希望能给其他有需要的人带来 ...

  6. 信息学奥赛一本通习题答案(三)

    最近在给小学生做C++的入门培训,用的教程是信息学奥赛一本通,刷题网址 http://ybt.ssoier.cn:8088/index.php 现将部分习题的答案放在博客上,希望能给其他有需要的人带来 ...

  7. 信息学奥赛一本通 提高篇 第六部分 数学基础 相关的真题

    第1章   快速幂 1875:[13NOIP提高组]转圈游戏 信息学奥赛一本通(C++版)在线评测系统 第2 章  素数 第 3 章  约数 第 4 章  同余问题 第 5 章  矩阵乘法 第 6 章 ...

  8. 信息学奥赛一本通题目代码(非题库)

    为了完善自己学c++,很多人都去读相关文献,就比如<信息学奥赛一本通>,可又对题目无从下手,从今天开始,我将把书上的题目一 一的解析下来,可以做参考,如果有错,可以告诉我,将在下次解析里重 ...

  9. 信息学奥赛一本通(C++版) 刷题 记录

    总目录详见:https://blog.csdn.net/mrcrack/article/details/86501716 信息学奥赛一本通(C++版) 刷题 记录 http://ybt.ssoier. ...

  10. 最近公共祖先三种算法详解 + 模板题 建议新手收藏 例题: 信息学奥赛一本通 祖孙询问 距离

    首先什么是最近公共祖先?? 如图:红色节点的祖先为红色的1, 2, 3. 绿色节点的祖先为绿色的1, 2, 3, 4. 他们的最近公共祖先即他们最先相交的地方,如在上图中黄色的点就是他们的最近公共祖先 ...

最新文章

  1. #27 回文数字 Palindrome Detector
  2. Kubernetes 稳定性保障手册 -- 可观测性专题
  3. zookeeper的ZAB协议学习
  4. 使用Mockito时遇到的一些问题
  5. excel删除空行_Excel里99.9%的人都踩过的坑,早看早避开!
  6. 【多项式求逆】[BZOJ3456]城市规划
  7. 一段oracle中的“复杂”分组统计sql
  8. java读取txt配置文件_Java程序读写配置文件(以纯文本.txt类型示例)
  9. 2020计算机校友会大学排名,2020年校友会大学排名:一个世界一流大学,一个中国一流大学...
  10. 苹果电脑怎么清理垃圾和缓存文件,mac如何清理系统缓存文件
  11. 名校400门免费人文社科公开课视频合集!
  12. QInputDialog,QTextEdit,QLineEdit,Qt右键菜单英文转中文问题
  13. Android Studio 连接第三方模拟器
  14. ■ 直接调用阿里云视频点播API实现视频播放
  15. ⚡️VR ✙ 深入浅出⚡️ | VR 简单介绍说明
  16. (亲测很实用)地理位置批量转经纬度,基于百度地图api
  17. 003 大数据4V特征
  18. [导入]雨音唱片-《音乐诗画 4CD》四季系列 320k/mp3(亲传)
  19. markdown语法总结
  20. 【单片机毕业设计】【mcuclub-jj-050】基于单片机的门禁的设计

热门文章

  1. 微型计算机系统中的内部寄存,微机原理与接口技术习题集汇总.doc
  2. python合并数组输出重复项_python - 不同数组项的所有可能组合[重复] - 堆栈内存溢出...
  3. 干加个偏旁可以变成什么字_面试官:“干”字加一笔,变成什么字?回答王和午字不对...
  4. React之函数中的this指向
  5. ES6 解构赋值详解
  6. unity中怎么在InspectorI面板加LOGO
  7. 图像二维离散傅里叶变换、幅度谱、相位谱
  8. 团队开发——个人工作总结04
  9. angular中的表单验证
  10. 字符搜索正则表达式语法详解