最佳买卖股票时机含冷冻期——动态规划

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

问题来源:力扣第309题

dp问题真tm难。


思路:

  1. \(dp[i][j]\) 表示第 \(i\) 天结束后的的第 \(j\) 个状态。

  2. \(0\) 代表已持有一支股票;\(1\) 代表无持有股票且处于冷冻期,\(2\) 代表无持有股票且不处于冷冻期。

  3. \(dp[i][0]\) 可以由 \(dp[i - 1][0]\) , \(dp[i - 1][2] - prices[i]\) 得来,所以 \(dp[i][0]\) 状态转移方程为:

\[dp[i][0] = max(dp[i - 1][0] , dp[i - 1][2] - prices[i]) \]

  1. \(dp[i][1]\) 为第 \(i\) 天处于冷冻期,所以今天必定卖出了股票,所以,\(dp[i][1]\) 状态转移方程为:

    \[dp[i][1] = dp[i - 1][0] + prices[i] \]

    \(dp[i][1]\) 转移方程中是 \(prices[i]\) 而不是 \(prices[i - 1]\) 的原因是 \(dp[i - 1][1]\) 是一天结束后的状态,所以当前一天结束状态为 \(0\) 状态时,则必定是当天卖出的股票,所以是加上 \(prices[i]\) 而不是加 \(prices[i - 1]\)

  2. \(dp[i][2]\) 为第 \(i\) 天为即没有持有股票且没有处于冷冻期,\(dp[i][2]\) 可以由 \(dp[i - 1][1]\) , \(dp[i - 1][2]\) 得到。所以 \(dp[i][2]\) 的状态转移方程为:

\[dp[i][2] = max(dp[i - 1][1] , dp[i - 1][2]) \]

c++ 代码

class Solution {
public:
    // dp[i][j]表示第 i 天结束后的状态
    // 0 代表已持有一支股票;1 代表无持有股票且处于冷冻期,2 代表无持有股票且不处于冷冻期。
    // dp[i][0] 可以由 dp[i - 1][0] , dp[i - 1][2] - prices[i]得来,所以dp[i][0]状态转移方程为 dp[i][0] = max(dp[i - 1][0] , dp[i - 1][2] - prices[i]);
    // dp[i][1] 为第 i 天处于冷冻期,所以今天必定卖出了股票,所以,dp[i][1] 状态转移方程为 dp[i][1] = dp[i - 1][0] + prices[i];
    // dp[i][2] 为第 i 天为即没有持有股票且没有处于冷冻期,dp[i][2] 可以由dp[i - 1][1] , dp[i - 1][2] 得到。所以 dp[i][2] 的状态转移方程为 dp[i][2] = max(dp[i - 1][1] , dp[i - 1][2])。
    int maxProfit(vector<int>& prices){
        int n = prices.size();
        vector<vector<int>> dp(n,vector<int>(3,0));
        dp[0][0] = -prices[0];
        for(int i = 1;i < n;i++){
            dp[i][0] = max(dp[i - 1][0] , dp[i - 1][2] - prices[i]);
            dp[i][1] = dp[i - 1][0] + prices[i];
            dp[i][2] = max(dp[i - 1][1] , dp[i - 1][2]);
        }
        int ans = max(dp[n - 1][1] , dp[n - 1][2]);
        return ans;
    }
};

代码优化

  • 由于 \(dp[i][j]\) 只与前一个状态有关,所以我们可以利用滚动数组来维护三个状态转移方程以减少内存消耗(即创建 \(2*3\) 的数组来对三个状态转移方程进行维护)。

c++ 代码

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

结果

image

posted @ 2022-01-11 23:33  clain  阅读(71)  评论(0)    收藏  举报