LeetCode每日一题——309.最佳买卖股票时机含冷冻期

184 阅读2分钟

309.最佳买卖股票时机含冷冻期

题目:

给定一个整数数组,其中第 i 个元素代表了第 i 天的股票价格 。

设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票):

你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。 卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。 示例:

输入: [1,2,3,0,2] 输出: 3 解释: 对应的交易状态为: [买入, 卖出, 冷冻期, 买入, 卖出]

解析:

假设我们用f(i)表示第i天结束后的收益,根据题目所说,我们是多次买卖一支股票,并且卖出股票后有1天的冷冻期,因此我们会有三种不同的情况:

  1. 持有股票,记为f(i)[0]
  2. 未持有股票,处于冷冻期,记为f(i)[1]
  3. 未持有股票,未处冷冻期,记为f(i)[2]

我们接着分析:

  1. 如果第i天是情况1,那么第i-1天要么是情况1,持有股票并第i天未卖出,要么是情况3,未持有股票且未处冷冻期并且在第i天买入,所以f(i)[0] = Math.max(f(i-1)[0], f(i-1)[2] - prices[i]);
  2. 如果第i天是情况2,那么第i-1天是情况1,持有股票并第i天卖出股票,所以f(i)[1] = f(i-1)[0] + prices[i];
  3. 如果第i天是情况3,那么第i-1天是情况2,处于冷冻期,要么是情况3,未持有股票且未处冷冻期并且在第i天未买入,所以f(i)[2] = Math.max(f(i-1)[1], f(i-1)[2] );

经以上分析,我们得出:

f(i)[0] = Math.max(f(i-1)[0], f(i-1)[2] - prices[i])
f(i)[1] = f(i-1)[0] + prices[i]
f(i)[2] = Math.max(f(i-1)[1], f(i-1)[2] )

f(i)只与f(i-1)有关系,我们可以用滚动数组来简化内存。

最后我们在考虑一下边界值,最后一天,股票直接卖掉,做到利益最大化。

代码如下:

public int maxProfit(int[] prices) {
    if (prices.length == 0) {
        return 0;
    }

    int n = prices.length;
    int f0 = -prices[0];
    int f1 = 0;
    int f2 = 0;
    for (int i = 1; i < n; ++i) {
        int newf0 = Math.max(f0, f2 - prices[i]);
        int newf1 = f0 + prices[i];
        int newf2 = Math.max(f1, f2);
        f0 = newf0;
        f1 = newf1;
        f2 = newf2;
    }

    return Math.max(f1, f2);
}

复杂度分析

  • 时间复杂度:O(n),其中 n 为数组prices 的长度。

  • 空间复杂度:O(1)。只用到了固定的空间。