309. Best Time to Buy and Sell Stock with Cooldown

Say you have an array for which the ith element is the price of a given stock on day i.

Design an algorithm to find the maximum profit. You may complete as many transactions as you like (ie, buy one and sell one share of the stock multiple times) with the following restrictions:

  • You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).
  • After you sell your stock, you cannot buy stock on next day. (ie, cooldown 1 day)

股票类问题最后一题:

Q:考虑时一直对于不知道休息几天的问题不好下手。

dp所表示的意义不能再是第i次交易或者第i天是买或卖的最大收益,因为如果这么定义 后一天是买还是卖或者休息取决于前所有天的不同决策取得的利益最大值。

A:  看过discussion思路后发现:第i天的买或者卖决策取决于上一个有效交易(既不包括中间休息天数) 那么定义buy[i]为截止第i天最后一个有效交易是买交易的最大利润 sell[i]为截止第i天最后一个有效交易是卖交易的最大利润

那么就有如下状态转移方程:

buy[i] = max(sell[i-2]-price[i], buy[i-1]) 第i天买或者休息取决于 上一次卖时的最大收益减去今天买的价格 或者上次买完不卖

sell[i] = max(buy[i-1]+price[i], sell[i-1]) 第i天卖或者休息取决于 上一次买时的最大收益加上今天卖的价格 或者上次卖完休息

思路非常巧妙

初始值:因为买的时候减price初始值为负数 所以买的dp要设成INT_MIN

 1 class Solution {
 2 public:
 3     int maxProfit(vector<int>& prices) {
 4         int n = prices.size()+2;
 5         vector<int> buy(n, INT_MIN);
 6         vector<int> sell(n, 0);
 7         for(int i = 2; i < n; i++)
 8         {
 9             buy[i] = max(sell[i-2] - prices[i-2], buy[i-1]);
10             sell[i] = max(buy[i-1] + prices[i-2], sell[i-1]);
11         }
12         return sell[n-1];
13     }
14 };

 

速度优化:只记录i,i-1,和i-2时的值

 1 class Solution {
 2 public:
 3     int maxProfit(vector<int>& prices) {
 4         int buy(INT_MIN), sell(0), prev_sell(0), prev_buy(0);
 5         for (int price : prices) {
 6             prev_buy = buy;
 7             buy = max(prev_sell - price, buy);
 8             prev_sell = sell;
 9             sell = max(prev_buy + price, sell);
10         }
11         return sell;
12     }
13 };