Solution 1
对 0121. Best Time to Buy and Sell Stock 的进一步扩展,在不限制同期买卖的情况下,仅能进行最多两次买卖的最大收益方案,显然是一个动态规划了。但是我还没学会这种多状态的动态规划
【参考官方】整个过程涉及到五个状态:什么都不做、第一次买入和卖出、第二次买入和卖出。由于第一个状态的收益会自动合并到其余的四个状态上(直接等于前一个状态),因此状态转移(即收益变化)为:
{ buy 1 = max { buy 1 , − prices [ i ] } sell 1 = max { sell 1 , buy 1 + prices [ i ] } buy 2 = max { buy 2 , sell 1 − prices [ i ] } sell 2 = max { sell 2 , buy 2 + prices [ i ] } \left\{\begin{array}{l}\text { buy }_{1}=\max \left\{\text { buy }_{1},-\text { prices }[i]\right\} \\\text { sell }_{1}=\max \left\{\text { sell }_{1}, \text { buy }_{1}+\text { prices }[i]\right\} \\\text { buy }_{2}=\max \left\{\text { buy }_{2}, \text { sell }_{1}-\text { prices }[i]\right\} \\\text { sell }_{2}=\max \left\{\text { sell }_{2}, \text { buy }_{2}+\text { prices }[i]\right\}\end{array}\right. ⎩⎪⎪⎨⎪⎪⎧ buy 1=max{ buy 1,− prices [i]} sell 1=max{ sell 1, buy 1+ prices [i]} buy 2=max{ buy 2, sell 1− prices [i]} sell 2=max{ sell 2, buy 2+ prices [i]}
同时,由于允许同期买卖,因此可以从上到下逐个更新,因为上一个项目的更新不影响下一个结果(相当于当前完成了一次买卖,额外收益为0,不影响结果)。
初始状态,两个买入状态初始化为即为第一天的负报价(状态为收益,买入即负收益,对于第二次买入,如上所属相当于这一天买了卖了又卖了,额外收益为0),两个卖出状态为0(因为没有本金)
- 时间复杂度: O ( N ) O(N) O(N),其中 N N N为输入长度,线性遍历
- 空间复杂度: O ( 1 ) O(1) O(1),仅维护常数个状态变量
class Solution {
public:
int maxProfit(vector<int>& prices) {
int buy1 = -prices[0], sell1 = 0;
int buy2 = -prices[0], sell2 = 0;
for (int i = 1; i < prices.size(); ++i) {
buy1 = max(buy1, -prices[i]);
sell1 = max(sell1, buy1 + prices[i]);
buy2 = max(buy2, sell1 - prices[i]);
sell2 = max(sell2, buy2 + prices[i]);
}
return sell2;
}
};
Solution 2
Solution 1的Python实现
class Solution:
def maxProfit(self, prices: List[int]) -> int:
buy1, sell1 = -prices[0], 0
buy2, sell2 = -prices[0], 0
for i in range(1, len(prices)):
buy1 = max(buy1, -prices[i])
sell1 = max(sell1, buy1 + prices[i])
buy2 = max(buy2, sell1 - prices[i])
sell2 = max(sell2, buy2 + prices[i])
return sell2