【必備演算法】動態規劃:一個思路解決六道股票問題
買賣股票系列一共有6道題,都是不斷交易一隻股票(股價通過price[]給出,陣列長度表示可以交易的天數)然後求最大利潤:
- 121. 買賣股票的最佳時機¹:股票只能交易一次
- 122. 買賣股票的最佳時機 II¹:股票可以交易無數次
- 123. 買賣股票的最佳時機 III³:股票可以交易2次
- 188. 買賣股票的最佳時機 IV³:股票可以交易K次
- 309. 最佳買賣股票時機含冷凍期²:可以交易無數次,但完成一筆交易(買+賣)後有一天冷卻期
- 714. 買賣股票的最佳含手續費²:可以交易無數次,但完成一筆交易(買+賣)後需要交手續費
現在我們要通過一種動態規劃的思路去通解上面六道題!
我們都知道,動態規劃的第一步是狀態定義,當成功且合適的定義了狀態,一道動態規劃問題就解決一半了。那上面的股票問題如何定義狀態呢?
因為最後求的都是最大利潤,所以狀態的含義肯定是maxprofit。但應該定義成幾維狀態呢?我們下面就從一維到三維逐一嘗試…
1.一維狀態:maxprofit[i]
- 狀態定義:
MP[i]
。第i天的最大利潤,取值[0, n) - 狀態方程:對於股票無非就兩種操作,買入和賣出
- 買入:
MP[i] = MP[i - 1] + (-p[i])
- 賣出:
MP[i] = MP[i - 1] + (p[i])
- 買入:
- 最終狀態:
MP[n - 1]
。第n天的最大利潤
問題:因為只能持有一股,所以買入和賣出的前提分別是未持有和持有,但是隻用這一位 i,根本就沒法知道是否持有啊,所以無法正確進行狀態遞推,所以只用一維不太行…
2.二維狀態:maxprofit[i][j]
- 狀態定義:
MP[i][j]
。第 i 天未持有股票(j=0)或持有股票(j=1)的最大利潤- i表示第i天,取值[0, n)
- j表示當前天是否持有股票,取值為 0或1
- 狀態方程:第i天時有兩種情況,有股票和沒股票。
- 第一種情況:我第i天沒有股票,即狀態
MP[i][0]
-
MP[i][0]
=MP[i-1][0]
表示我沒股票不操作 -
MP[i][0]
=MP[i - 1][1] + p[i]
表示我賣出股票==> 然後再對這兩種情況情況求最值,即
MP[i][0] = max(MP[i-1][0], MP[i - 1][1] + p[i])
-
- 第二種情況:我第i天有1股,即狀態
MP[i][1]
:-
MP[i][1]
=MP[i-1][1]
表示我持股票不操作 -
MP[i][0]
=MP[i - 1][0] - p[i]
表示我買入股票==> 然後再對這兩種情況情況求最值,即
MP[i][1] = max(MP[i-1][1], MP[i - 1][0] - p[i])
-
- 第一種情況:我第i天沒有股票,即狀態
- 最終狀態:
MP[n-1][0]
。i=n-1沒什麼說的,j=0是因為市場都熄火了,你還持有著股票(j=1)肯定是不值的,就算虧了也要賣掉回點老本
問題:對於前三道題(交易1次,無數次,2次)可以這麼搞,但是如果設定只可以交易K次,那我在狀態遞推時怎麼知道前面已經交易多少次,接下來還能不能交易了?所以二維狀態雖然可行,但是不夠通用…
3.三維狀態:maxprofit[i][k][j]
-
狀態定義:
MP[i][k][j]
。表數第 i 天且已經交易了k次的時,未持有和持有股票的最大利潤- i表示第i天,取值[0, n)
- k表示到今天(第i天)已經交易了k次,取值 [0, K]
- j表示當前天是否持有股票,取值為 0或1
-
狀態方程:同上,第i天的時候也是分為兩種情況,未持有股票和持有股票。
-
第一種情況:我第 i 天沒有股票且交易k次 ,即狀態
MP[i][k][0]
-
MP[i][k][0]
=MP[i-1][k][0]
表示我沒股票不操作 -
MP[i][k][0]
=MP[i - 1][k-1][1]+ p[i]
表示我賣出股票==> 然後再對這兩種情況情況求最值,即
MP[i][k][0] = max(MP[i-1][k][0], MP[i - 1][k-1][1] + p[i])
-
-
第二種情況:我第 i 天持有股票且交易 k 次,即狀態
MP[i][k][1]
-
MP[i][k][1]
=MP[i-1][k][1]
表示我持股票不操作 -
MP[i][k][1]
=MP[i - 1][k-1][0] - p[i]
表示我買入股票==> 然後再對這兩種情況情況求最值,即
MP[i][k][1] = max(MP[i-1][k][1], MP[i - 1][k-1][0] - p[i])
-
-
-
最終狀態:
max(MP[n-1][0..K][0])
。遍歷交易0-K次看然後找最值
時間複雜度O(N*K*2)
,空間複雜度也是O(N*K*2)
。
問題:如果是有冷卻期的話,因為不限制交易次數,所以可以用k記錄是否在冷卻期。
好了,思路分析就到這裡,具體動態規劃程式碼請看:
相關文章
- 從“股票問題”談動態規劃問題的解決思路動態規劃
- 動態規劃,股票問題留坑動態規劃
- 動態規劃之股票問題123動態規劃
- 動態規劃做題思路動態規劃
- 淺談動態規劃以及相關的股票問題動態規劃
- 【動態規劃】買賣股票動態規劃
- 掌握動態規劃,從“什麼問題適合用”及“解題思路”入手動態規劃
- 應用動態規劃思想解決實際問題動態規劃
- Leetcode 題解系列 -- 股票的最大利潤(動態規劃)LeetCode動態規劃
- 最小總和問題(動態規劃演算法)動態規劃演算法
- “插花問題”的動態規劃法演算法動態規劃演算法
- 插花問題的“動態規劃法”演算法動態規劃演算法
- Java演算法之動態規劃詳解-買賣股票最佳時機Java演算法動態規劃
- 買賣股票相關演算法-動態規劃-python演算法動態規劃Python
- 動態規劃,這幾個問題最常見!動態規劃
- 動態規劃解題方法動態規劃
- 淺談什麼是動態規劃以及相關的「股票」演算法題動態規劃演算法
- 01揹包問題理解動態規劃演算法動態規劃演算法
- 動態規劃之子序列問題動態規劃
- 揹包問題----動態規劃動態規劃
- 【動態規劃】揹包問題動態規劃
- 整數劃分問題(動態規劃)動態規劃
- Leetcode 題解演算法之動態規劃LeetCode演算法動態規劃
- 使用動態規劃完美解決硬幣找零問題(Python)動態規劃Python
- 動態規劃 擺花 題解動態規劃
- 動態規劃解0-1揹包問題動態規劃
- 動態規劃_備忘錄法_矩陣鏈乘問題動態規劃矩陣
- 【演算法】動態規劃-優化編輯器問題演算法動態規劃優化
- 【動態規劃(一)】動態規劃基礎動態規劃
- 動態規劃 01揹包問題動態規劃
- 找零問題與動態規劃動態規劃
- 【動態規劃】01揹包問題動態規劃
- 動態規劃-01揹包問題動態規劃
- 動態規劃篇——揹包問題動態規劃
- 醜數問題——動態規劃、Java動態規劃Java
- (動態規劃)最小分糖果問題動態規劃
- 動態規劃--01揹包問題動態規劃
- 演算法(七):圖解動態規劃演算法圖解動態規劃