leetcode
leetcode 251 ~ 300
买卖股票的最佳时机含冷冻期

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

难度:

标签:

题目描述

给定一个整数数组prices,其中第  prices[i] 表示第 i 天的股票价格 。​

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

  • 卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。

注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

 

示例 1:

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

示例 2:

输入: prices = [1]
输出: 0

 

提示:

  • 1 <= prices.length <= 5000
  • 0 <= prices[i] <= 1000

代码结果

运行时间: 48 ms, 内存: 15.1 MB


/**
 * Using Java Streams for a more functional approach is challenging in this problem since it's DP-based.
 * The state transitions require prior state knowledge. However, we can still use streams for processing input data.
 * Note: This implementation is mostly for demonstrating usage of streams and may not be efficient.
 */
import java.util.stream.IntStream;
public class SolutionStream {
    public int maxProfit(int[] prices) {
        if (prices == null || prices.length == 0) return 0;
        int n = prices.length;
        int[] hold = new int[n];
        int[] sold = new int[n];
        int[] rest = new int[n];
        hold[0] = -prices[0];
        sold[0] = 0;
        rest[0] = 0;
        IntStream.range(1, n).forEach(i -> {
            hold[i] = Math.max(hold[i - 1], rest[i - 1] - prices[i]);
            sold[i] = hold[i - 1] + prices[i];
            rest[i] = Math.max(rest[i - 1], sold[i - 1]);
        });
        return Math.max(sold[n - 1], rest[n - 1]);
    }
}

解释

方法:

这个题解使用了动态规划的思路。定义了状态 dp[i][0] 表示第 i 天结束时,不持有股票的最大利润;dp[i][1] 表示第 i 天结束时,持有股票的最大利润。然后通过状态转移方程,不断更新每一天的这两个状态值,最终得到最大利润。状态转移考虑了冷冻期的限制,即卖出股票后的第二天无法买入股票。

时间复杂度:

O(n)

空间复杂度:

O(n)

代码细节讲解

🦆
在状态转移方程中,为什么dp[i][1]的计算需要从dp[i-2][0]开始?这与冷冻期有什么关系?
在题目中,冷冻期的规定是在卖出股票的第二天不能买入股票。因此,如果第 i 天选择买入股票,那么第 i-1 天不能进行交易(即不能卖出股票),所以买入的资金应该来自于第 i-2 天或更早时不持有股票的最大利润。因此,dp[i][1]的计算需要考虑dp[i-2][0]的状态,即从第 i-2 天的不持有股票的状态转移而来。
🦆
为什么在动态规划的初始条件中,dp[0][1] 设置为负无穷?这样的设置对算法有什么影响?
dp[0][1] 设置为负无穷是因为在第 0 天,也就是开始之前,不可能持有股票,因此这种状态是非法的。将其设置为负无穷可以确保在进行状态转移时,任何基于 dp[0][1] 的计算都不会被错误地考虑为有效选项,从而维护动态规划逻辑的正确性。
🦆
在动态规划中,更新持有股票的最大利润时,为什么要用dp[i-2][0]而不是dp[i-1][0]来减去prices[i-1]?
这是因为题目中包含一个冷冻期的要求,即在卖出股票后的下一天不能进行股票买入。如果使用 dp[i-1][0] 来计算 dp[i][1],则意味着在第 i-1 天卖出股票后,第 i 天立即买入,这违反了冷冻期的规则。因此,必须使用 dp[i-2][0],这表示在第 i-2 天或更早卖出股票后,至少经过一天的冷冻期,第 i 天才能买入股票。
🦆
在最后返回dp[-1][0]时,是否考虑了所有可能的情况,包括最后一天刚好卖出股票的情况?
是的,最后返回 dp[-1][0] 时考虑了所有可能的情况。dp[i][0] 的状态包括了在第 i 天卖出股票所获得的最大利润,因此 dp[-1][0] 表示在最后一天或之前的任何一天卖出股票后所能获得的最大利润。这确保了算法输出的结果包括了可能在最后一天卖出股票的情况。

相关问题

买卖股票的最佳时机

给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。

你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。

返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0

 

示例 1:

输入:[7,1,5,3,6,4]
输出:5
解释:在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
     注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。

示例 2:

输入:prices = [7,6,4,3,1]
输出:0
解释:在这种情况下, 没有交易完成, 所以最大利润为 0。

 

提示:

  • 1 <= prices.length <= 105
  • 0 <= prices[i] <= 104

买卖股票的最佳时机 II

给你一个整数数组 prices ,其中 prices[i] 表示某支股票第 i 天的价格。

在每一天,你可以决定是否购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以先购买,然后在 同一天 出售。

返回 你能获得的 最大 利润 。

 

示例 1:

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

示例 2:

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

示例 3:

输入:prices = [7,6,4,3,1]
输出:0
解释:在这种情况下, 交易无法获得正利润,所以不参与交易可以获得最大利润,最大利润为 0 。

 

提示:

  • 1 <= prices.length <= 3 * 104
  • 0 <= prices[i] <= 104