一、题目309:
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)
示例:
Input: [1,2,3,0,2]
Output: 3
Explanation: transactions = [buy, sell, cooldown, buy, sell]
二、分析
由于是股票,所以又买也有卖,一般需要设置两个dp数组进行状态保存,由于中间有一段时间的冷却,所以也可以设置三个数组(买、卖、冷却)来进行状态存储,设置三个数组,并进行题解稍显繁琐,具体可以参见:
https://www.cnblogs.com/grandyang/p/4997417.html
https://www.cnblogs.com/jdneo/p/5228004.html
方法一:
引入辅助数组sells
和buys:
-
sells[i]表示在第i天卖出股票所能获得的最大累积收益 buys[i]表示在第i天买入股票所能获得的最大累积收益 初始化令sells[0] = 0,buys[0] = -prices[0]
第i天交易时获得的累计收益只与第i-1天与第i-2天有关
记第i天与第i-1天的价格差:delta = price[i] - price[i - 1]
状态转移方程为:
sells[i] = max(buys[i - 1] + prices[i], sells[i - 1] + delta)
buys[i] = max(sells[i - 2] - prices[i], buys[i - 1] - delta)
含义为:
第i天卖出的最大累积收益 = max(第i-1天买入~第i天卖出的最大累积收益, 第i-1天卖出后反悔~改为第i天卖出的最大累积收益)
第i天买入的最大累积收益 = max(第i-2天卖出~第i天买入的最大累积收益, 第i-1天买入后反悔~改为第i天买入的最大累积收益)
最终结果为sells.back(),只有卖了才有收益。
方法二:
方法二由方法一拓展而来:
第i-1天卖出后反悔,改为第i天卖出 等价于 第i-1天持有股票,第i天再卖出
第i-1天买入后反悔,改为第i天买入 等价于 第i-1天没有股票,第i天再买入
所以,这里,改变辅助数组的意义:
sells[i]表示在第i天不持有股票所能获得的最大累计收益
buys[i]表示在第i天持有股票所能获得的最大累计收益
状态转移方程:
sells[i] = max(sells[i - 1], buys[i - 1] + prices[i])
buys[i] = max(buys[i - 1], sells[i - 2] - prices[i])
其中,但i<2时:buys[i] = max(buys[i - 1], - prices[i]);
最终结果为sells.back();
代码示例如下:
class Solution {
public:
int maxProfit(vector<int>& prices) {
if (prices.empty())
return 0;
vector<int> Buy(prices.size(), 0);//表示第i天,手中持有股票
vector<int> Sell(prices.size(), 0); //表示第i天,手中没有股票
Buy[0] = -prices[0];
for (int i = 1; i < prices.size(); i++)
{
Sell[i] = max(Buy[i - 1] + prices[i], Sell[i - 1]);
if (i >= 2)
Buy[i] = max(Sell[i - 2] - prices[i], Buy[i - 1]);
else
Buy[i] = max(-prices[i], Buy[i - 1]);
}
return Sell[prices.size() - 1];
}
};