44-best-time-to-buy-and-sell-stock-with-cooldown 力扣 309. 買賣股票的最佳時機包含冷凍期

老马啸西风發表於2024-11-09

買賣股票系列

【leetcode】40-best-time-to-buy-and-sell-stock 力扣 121. 買賣股票的最佳時機

【leetcode】41-best-time-to-buy-and-sell-stock-ii 力扣 122. 買賣股票的最佳時機 II

【leetcode】42-best-time-to-buy-and-sell-stock-iii 力扣 123. 買賣股票的最佳時機 III

【leetcode】43-best-time-to-buy-and-sell-stock-iv 力扣 188. 買賣股票的最佳時機 IV

【leetcode】44-best-time-to-buy-and-sell-stock-with-cooldown 力扣 309. 買賣股票的最佳時機包含冷凍期

【leetcode】45-best-time-to-buy-and-sell-stock-with-cooldown 力扣 714. 買賣股票的最佳時機包含手續費

開源地址

為了便於大家學習,所有實現均已開源。歡迎 fork + star~

https://github.com/houbb/leetcode

題目

給定一個整數陣列prices,其中第 prices[i] 表示第 i 天的股票價格 。​

設計一個演算法計算出最大利潤。在滿足以下約束條件下,你可以儘可能地完成更多的交易(多次買賣一支股票):

賣出股票後,你無法在第二天買入股票 (即冷凍期為 1 天)。
注意:你不能同時參與多筆交易(你必須在再次購買前出售掉之前的股票)。

示例 1:

輸入: prices = [1,2,3,0,2]
輸出: 3
解釋: 對應的交易狀態為: [買入, 賣出, 冷凍期, 買入, 賣出]
示例 2:

輸入: prices = [1]
輸出: 0

提示:

1 <= prices.length <= 5000
0 <= prices[i] <= 1000

v1-DP

整體思路

我們考慮 3 個場景:

// a1: 手上持有股票的最大收益
// a2: 手上不持有股票,並且處於冷凍期中的累計最大收益
// a3: 手上不持有股票,並且不在冷凍期中的累計最大收益

要想計算最大的利潤,只需要考慮不持有股票的對比就可。

至於 a1,是為了中轉計算。

初始化

a1[0] = -prices[0];

遞推公式

a1

a1 什麼時候手上會有股票? 必須是買入的時候。

一種是上次就持有;還有一種處於 a3 狀態,然後買入。

a1[i] = max(a1[i-1], a3[i-1] - prices[i]);

a2

a2: 手上不持有股票,並且處於冷凍期中的累計最大收益

什麼場景會不持有,則處於冷凍期?

就是持有股票,然後直接賣出了?

a2[i] = a1[i-1] + prices[i];

a3

a3: 手上不持有股票,並且不在冷凍期中的累計最大收益

什麼場景不持有股票,且不處於冷凍期。

1)此時不能直接賣出,因為會被冷凍;所以

2)昨天分為兩個場景:a2 狀態;或者 a3 狀態

a3[i] = max(a3[i-1], a2[i-1])

完整的虛擬碼

class Solution {
    
    public int maxProfit(int[] prices) {
        int n = prices.length;
        // a1: 手上持有股票的最大收益   主要是為了計算儲存,結果不考慮此場景。
        // a2: 手上不持有股票,並且處於冷凍期中的累計最大收益
        // a3: 手上不持有股票,並且不在冷凍期中的累計最大收益
        int a1[] = new int[n];
        int a2[] = new int[n];
        int a3[] = new int[n];

        // 初始化
        a1[0] = -prices[0];

        for (int i = 1; i < n; ++i) {
            // 持有股票:昨天持有 OR 買入
            a1[i] = Math.max(a1[i-1], a3[i-1] - prices[i]);

            // 手上不持有股票,並且處於冷凍期中的累計最大收益: 必定是賣出
            a2[i] = a1[i-1] + prices[i];

            // 手上不持有股票,並且不在冷凍期中的累計最大收益:  昨天可能是 a3; a2
            a3[i] = Math.max(a2[i-1], a3[i-1]);
        }

        // 手裡沒有股票對比即可
        return Math.max(a2[n-1], a3[n-1]);
    }
    
}

評價

這一道題嚴格點說還是比較難的,就是我們必須透過 3 個狀態陣列來處理。

所以需要前面題目的鋪墊。

相關文章