又是小垃圾写不出力扣,看题解cv的一天
~~

题目描述

给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格。
设计一个算法来计算你所能获取的最大利润。你最多可以完成 两笔 交易。
注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

传送门

输入输出样例

  1. 输入:prices = [3,3,5,0,0,3,1,4]
  2. 输出:6
  3. 解释:在第 4 天(股票价格 = 0)的时候买入,在第 6 天(股票价格 = 3)的时候卖出,这笔交易所能获得利润 = 3-0 = 3
  4. 随后,在第 7 天(股票价格 = 1)的时候买入,在第 8 (股票价格 = 4)的时候卖出,这笔交易所能获得利润 = 4-1 = 3

题解

方法:DP

由于我们最多可以完成两笔交易,因此在任意一天结束之后,我们会处于以下五个状态中的一种:

  • 未进行过任何操作;
  • 只进行过一次买操作;
  • 进行了一次买操作和一次卖操作,即完成了一笔交易;
  • 在完成了一笔交易的前提下,进行了第二次买操作;
  • 完成了全部两笔交易。

由于第一个状态的利润显然为 00,因此我们可以不用将其记录。对于剩下的四个状态,我们分别将它们的最大利润记为 buy1, sell1, buy2, sell2。

如果我们知道了第 i−1 天结束后的这四个状态,那么如何通过状态转移方程得到第 i 天结束后的这四个状态呢?

对于 buy1 而言,在第 i 天我们可以不进行任何操作,保持不变,也可以在未进行任何操作的前提下以 prices[i] 的价格买入股票,那么 buy1 的状态转移方程即为:
buy1* = max{buy1, -prices[i]}
这里我们用buy1*来表示第 i 天的状态,用buy1来表示第 i-1 天的状态

对 sell1 而言,第 i 天我们可以不进行任何操作,也可以在只进行一次买操作的前提下 ,以 prices[i] 的价格卖出,所以 sell1 的状态转移为:
sell1* = max{sell1, buy1* + prices[i]}

同理可得 buy2 和 sell2 的状态转移。

在考虑边界条件时,我们需要理解下面的这个事实:

无论题目中是否允许「在同一天买入并且卖出」这一操作,最终的答案都不会受到影响,这是因为这一操作带来的收益为零。

Capture.PNG

代码

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int n = prices.size();
        int buy1 = -prices[0], sell1 = 0;
        int buy2 = -prices[0], sell2 = 0;
        for (int i = 1; i < n; ++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;
    }
};

复杂度分析

  • 时间复杂度:O(n)
  • 空间复杂度:O(1)

类似题目

贴一个买卖股票的进阶,把买卖次数变成了k次:传送门