参考:团灭股票问题
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; } };