309. Best Time to Buy and Sell Stock with Cooldown

参考:团灭股票问题

base问题:188. Best Time to Buy and Sell Stock IV

问题:

股票问题:

给出一组一支股票每日的价格数组。prices[]

每一天的操作可以为:买buy,卖sell,不操作rest

在第二次buy之前,需要离上一次sell隔一天冷静期,求可获得的最大收益是多少。

Example:

Input: [1,2,3,0,2]
Output: 3 
Explanation: transactions = [buy, sell, cooldown, buy, sell]

  

解法:DP(动态规划)

1.确定【状态】:

  • 当前的天数:第 i 天
  • 当前经过的交易次数:第 k 次
  • 当前的股票持有状况:p:0未持有(待买入),1 持有(待卖出)

2.确定【选择】:

  • 当前p=0(未持有,待买入状态):
    • 选择 1 :由本日卖出sell导致:dp[i-1][k][1]+prices[i] (昨天持股+今天卖出prices[i])
    • 选择 2:本日不操作rest:  dp[i-1][k][0]             (昨天未持股+今天不操作)
  • 当前p=1(持有,待卖出状态):
    • 选择 1 :由本日买入buy导致:dp[i-2][k][0]-prices[i] (天未持股+今天买入prices[i])
    • 选择 2:本日不操作rest:  dp[i-1][k][1]              (昨天持股+今天不操作)

3. dp[i][k][p]的含义:

今天为第i天,交易k次,持有状态为p的状态下,持有的最大收益。

4. 状态转移:

dp[i][p]= 

  • 当前p=0(未持有,待买入状态):MAX {
    • 选择 1 :由本日卖出sell导致:dp[i-1][1]+prices[i] (昨天持股+今天卖出prices[i])
    • 选择 2:本日不操作rest:  dp[i-1][0]             (昨天未持股+今天不操作) }
  • 当前p=1(持有,待卖出状态):MAX {
    • 选择 1 :由本日买入buy导致:dp[i-2][0]-prices[i] (前天未持股+今天买入prices[i])
    • 选择 2:本日不操作rest:  dp[i-1][1]              (昨天持股+今天不操作)}

5. base case:

  • i==0
    • dp[0][0]= 0
    • dp[0][1]= -∞(不可能存在的情况,用-∞表示)
  • 当i==1的时候,求dp[i][1]时,需要知道dp[i-2][0],按照dp[i][1]含义在第一天的时候
    • 由本日买入buy:-princes[i] ->因此,此时相当于dp[i-2][0]=0
    • 本日不操作rest:dp[0][1]

代码参考:

 1 class Solution {
 2 public:
 3     //dp[i][k][p]: ignore k
 4     //case_1: now without position: = max(sell , rest)
 5     //        dp[i][k][0] = max(dp[i-1][k][1]+prices[i], dp[i-1][k][0])
 6     //case_2: now with position: = max(buy , rest)
 7     //        dp[i][k][1] = max(dp[i-2][k-1][0]-prices[i], dp[i-1][k][1])
 8     //base case:
 9     //dp[0][0] = 0;  0-th day without position
10     //dp[0][1] = -infinite;  (imposible)0-th day with position
11     int maxProfit(vector<int>& prices) {
12         int n = prices.size();
13         vector<vector<int>> dp(n+1, vector<int>(2, 0));
14         dp[0][1] = INT_MIN;
15         for(int i=1; i<=n; i++) {
16             dp[i][0] = max(dp[i-1][1]+prices[i-1], dp[i-1][0]);
17             if(i==1) dp[i][1] = -prices[i-1];
18             else dp[i][1] = max(dp[i-2][0]-prices[i-1], dp[i-1][1]);
19         }
20         return dp[n][0];
21     }
22 };

♻️ 优化:

空间复杂度:2维->1维

去掉 i 

需要前一次的dp[][0], dp[][1] ->dp_0, dp_1

还有前前一次的dp[][0]  ->dp_0_pre

 

代码参考:

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int n = prices.size();
        int dp_0=0, dp_1=INT_MIN;
        int dp_0_pre=0;//if(i==1) dp[i][1] = -prices[i-1];
        for(int i=1; i<=n; i++) {
            int tmp = dp_0;
            dp_0 = max(dp_1+prices[i-1], dp_0);
            dp_1 = max(dp_0_pre-prices[i-1], dp_1);
            dp_0_pre = tmp;
        }
        return dp_0;
    }
};

 

posted @ 2020-09-17 17:07  habibah_chang  阅读(146)  评论(0编辑  收藏  举报