一文总结买卖股票的最佳时机的所有情况(附Python代码)
序言:
在數據結構與算法中的動態規劃部分,買賣股票系列題目多,題解相似,值得對比總結一下。希望小伙伴們在看過這篇文章之后,可以對動態規劃系列有一個清晰的認識,那么我們開始吧。
【注】本文部分參考于{代碼隨想錄}公眾號,想看詳細解說的可以移步。
Leedcode121.買賣股票的最佳時機
問題描述:
股票只能買賣一次,求最大利潤
解題思路:
dp[i][0] 表示第i天持有股票所剩得現金。(負的,即花了多少錢)
dp[i][1] 表示第i天不持有股票所得現金。
如果第i天持有股票即dp[i][0], 那么可以由兩個狀態推出來:
(1)第i-1天就持有股票,那么就保持現狀,所得現金就是昨天持有股票的所得現金即:dp[i - 1][0]
(2)第i天買入股票,所得現金就是買入今天的股票后所得現金即:-prices[i] 所以dp[i][0] = max(dp[i - 1][0], -prices[i]);
如果第i天不持有股票即dp[i][1], 也可以由兩個狀態推出來
(1)第i-1天就不持有股票,那么就保持現狀,所得現金就是昨天不持有股票的所得現金即:dp[i - 1][1]
(2)第i天賣出股票,所得現金就是按照今天股票佳價格賣出后所得現金即:prices[i] + dp[i - 1][0] 所以dp[i][1] = max(dp[i - 1][1], prices[i] + dp[i - 1][0]);
Leedcode122.買賣股票的最佳時機II
問題描述
可以多次買賣股票,問最大收益。
解題思路
dp[i][0] 表示第i天持有股票所得現金
dp[i][1] 表示第i天不持有股票所得最多現金
如果第i天持有股票即dp[i][0], 那么可以由兩個狀態推出來
(1)第i-1天就持有股票,那么就保持現狀,所得現金就是昨天持有股票的所得現金 即:dp[i - 1][0]
(2)第i天買入股票,所得現金就是昨天不持有股票的所得現金減去 今天的股票價格 即:dp[i - 1][1] - prices[i]。【注意】這里是和上一題(121.買賣股票的最佳時機)唯一不同的地方
在上一題中,因為股票全程只能買賣一次,所以如果買入股票,那么第i天持有股票即dp[i][0]一定就是 -prices[i]。
而本題,因為一只股票可以買賣多次,所以當第i天買入股票的時候,所持有的現金可能有之前買賣過的利潤。
如果第i天不持有股票即dp[i][1], 也可以由兩個狀態推出來
(1)第i-1天就不持有股票,那么就保持現狀,所得現金就是昨天不持有股票的所得現金即:dp[i - 1][1]
(2)第i天賣出股票,所得現金就是按照今天股票佳價格賣出后所得現金即:prices[i] + dp[i - 1][0] 所以dp[i][1] = max(dp[i - 1][1], prices[i] + dp[i - 1][0]);
Leedcode123.買賣股票的最佳時機III
問題描述
最多買賣兩次,問最大收益。
解題思路
一天一共就有五個狀態
0. 沒有操作
1.第一次買入
2.第一次賣出
3.第二次買入
4.第二次賣出
dp[i][j]中 i表示第i天,j為 [0 - 4] 五個狀態,dp[i][j]表示第i天狀態j所剩最大現金。
達到dp[i][1]狀態,有兩個具體操作:
(1)第i天買入股票了,那么dp[i][1] = dp[i-1][0] - prices[i]
(2)第i天沒有操作,而是沿用前一天買入的狀態,即:dp[i][1] = dp[i - 1][1]
dp[i][1] = max(dp[i-1][0] - prices[i], dp[i - 1][1]);
同理dp[i][2]也有兩個操作:
(1)第i天賣出股票了,那么dp[i][2] = dp[i - 1][1] + prices[i]
(2)第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] = 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]);
Leedcode188.買賣股票的最佳時機IV
問題描述
最多買賣k筆交易,問最大收益。
解題思路
使用二維數組 dp[i][j] :第i天的狀態為j,所剩下的最大現金是dp[i][j]
j的狀態表示為:
0 表示不操作
1 第一次買入
2 第一次賣出
3 第二次買入
4 第二次賣出
…
也就是說:除了0以外,偶數就是賣出,奇數就是買入。
達到dp[i][1]狀態,有兩個具體操作:
(1)第i天買入股票了,那么dp[i][1] = dp[i - 1][0] - prices[i]
(2)第i天沒有操作,而是沿用前一天買入的狀態,即:dp[i][1] = dp[i - 1][1]
dp[i][1] = max(dp[i - 1][0] - prices[i], dp[i - 1][0]);
同理dp[i][2]也有兩個操作:
(1)第i天賣出股票了,那么dp[i][2] = dp[i - 1][1] + prices[i]
(2)第i天沒有操作,沿用前一天賣出股票的狀態,即:dp[i][2] = dp[i - 1][2]
dp[i][2] = max(dp[i - 1][i] + prices[i], dp[i][2])
Leedcode309.最佳買賣股票時機含冷凍期
問題描述
可以多次買賣,但每次賣出有冷凍期1天。
解題思路
dp[i][j]:第i天狀態為j,所剩的最多現金為dp[i][j]。
具體可以區分出如下四個狀態:
狀態一:買入股票狀態(今天買入股票,或者是之前就買入了股票然后沒有操作)
狀態二:兩天前就賣出了股票,度過了冷凍期,一直沒操作,今天保持賣出股票狀態
狀態三:今天賣出了股票
狀態四:今天為冷凍期狀態,但冷凍期狀態不可持續,只有一天!
達到買入股票狀態dp[i][0],有兩個具體操作:
(1)前一天就是持有股票狀態(狀態一),dp[i][0] = dp[i - 1][0]
(2)今天買入了,有兩種情況
(2.1)前一天是冷凍期(狀態四),dp[i - 1][3] - prices[i]
(2.2)前一天是保持賣出股票狀態(狀態二),dp[i - 1][1] - prices[i]
2.1和2.2取最大值,即:max(dp[i - 1][3], dp[i - 1][1]) - prices[i]
即:dp[i][0] = max(dp[i - 1][0], max(dp[i - 1][3], dp[i - 1][1]) - prices[i]);
達到保持賣出股票狀態dp[i][1],有兩個具體操作:
(1)前一天就是狀態二
(2)前一天是冷凍期(狀態四)
即:dp[i][1] = max(dp[i - 1][1], dp[i - 1][3]);
達到今天就賣出股票狀態dp[i][2] ,只有一個操作:
(1)昨天一定是買入股票狀態(狀態一),今天賣出
即:dp[i][2] = dp[i - 1][0] + prices[i];
達到冷凍期狀態dp[i][3],只有一個操作:
(1)昨天賣出了股票(狀態三)
即:p[i][3] = dp[i - 1][2];
Leedcode714.買賣股票的最佳時機含手續費
問題描述
可以多次買賣,但每次有手續費。
解題思路
相對于122.買賣股票的最佳時機II,本題只需要在計算賣出操作的時候減去手續費就可以了,代碼幾乎是一樣的。
dp[i][0] 表示第i天持有股票所省最多現金。
dp[i][1] 表示第i天不持有股票所得最多現金
如果第i天持有股票即dp[i][0], 那么可以由兩個狀態推出來
第i-1天就持有股票,那么就保持現狀,所得現金就是昨天持有股票的所得現金 即:dp[i - 1][0]
第i天買入股票,所得現金就是昨天不持有股票的所得現金減去 今天的股票價格 即:dp[i - 1][1] - prices[i]
即:dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] - prices[i]);
如果第i天不持有股票即dp[i][1]的情況, 依然可以由兩個狀態推出來
第i-1天就不持有股票,那么就保持現狀,所得現金就是昨天不持有股票的所得現金 即:dp[i - 1][1]
第i天賣出股票,所得現金就是按照今天股票價格賣出后所得現金,注意這里需要有手續費了即:dp[i - 1][0] + prices[i] - fee
所以:dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] + prices[i] - fee);
總結
好啦,以上就是關于動態規劃中買賣股票的最佳時機的所有情況啦,喜歡的小伙伴可以點個贊哦,若是能關注就更好啦,作者會不定期更新總結Leedcode題解,以及發布一些關于機器視覺的內容~
總結
以上是生活随笔為你收集整理的一文总结买卖股票的最佳时机的所有情况(附Python代码)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 通俗易懂物联网(3):物联网产业链
- 下一篇: 测试开发之Python核心笔记(15):