80题|豆包MarsCode AI刷题

107 阅读3分钟

问题描述

小R近期表现出色,公司决定以股票的形式给予奖励,并允许他在市场上进行交易以最大化收益。给定一个数组,数组中的第 i 个元素代表第 i 天的股票价格。小R需要设计一个算法来实现最大利润。

股票交易规则如下:

  • 小R可以多次买卖股票,但在买入新的股票前必须卖出之前的股票。
  • 每次卖出股票后存在一天的冷冻期,在冷冻期内小R不能购买股票。

你的任务是帮助小R计算出在遵守交易规则的情况下能够获得的最大利润。

  • stocks: 一个整数列表,表示连续几天内的股票价格。 思路分析

这道题目要求设计一个算法来最大化股票交易的利润,具有以下特点:

  1. 交易规则:可以多次买入和卖出,但卖出后必须有一天的冷却期,期间不能再次买入。
  2. 目标:在整个交易过程中,获取的总利润最大化。
  3. 限制条件:每次买入需要卖出才能再买入,不能同时持有多个股票。

为了解决这个问题,我们可以使用动态规划(DP)来实现。动态规划的核心是将复杂问题分解为多个子问题,并通过递推公式高效地解决。


核心思想

动态规划通过定义状态来跟踪每天的决策和对应的最大利润。本题可以用三种状态来表示:

  1. hold[i]:第 ( i ) 天手里持有股票时的最大利润。
  2. cooldown[i]:第 ( i ) 天刚卖出股票(处于冷却期)的最大利润。
  3. rest[i]:第 ( i ) 天未持有股票,且没有处于冷却期的最大利润。

每个状态都有对应的递推公式,这些公式用来更新每天的最大利润。


状态转移方程

  1. hold[i]

    • 第 ( i ) 天持有股票的最大利润有两种可能:
      1. 第 ( i-1 ) 天已经持有股票,不进行任何操作,利润为 hold[i-1]
      2. 第 ( i-1 ) 天未持有股票且不处于冷却期,今天买入股票,利润为 rest[i-1] - stocks[i]
    • 状态转移方程: [ hold[i] = \max(hold[i-1], rest[i-1] - stocks[i]) ]
  2. cooldown[i]

    • 第 ( i ) 天处于冷却期的最大利润,只有一种可能:
      • 第 ( i-1 ) 天持有股票,并在今天卖出股票,利润为 hold[i-1] + stocks[i]
    • 状态转移方程: [ cooldown[i] = hold[i-1] + stocks[i] ]
  3. rest[i]

    • 第 ( i ) 天未持有股票且不处于冷却期的最大利润有两种可能:
      1. 第 ( i-1 ) 天也处于休息状态,利润为 rest[i-1]
      2. 第 ( i-1 ) 天处于冷却期,利润为 cooldown[i-1]
    • 状态转移方程: [ rest[i] = \max(rest[i-1], cooldown[i-1]) ]
  4. 初始条件

    • 第一天持有股票:hold[0] = -stocks[0](买入股票,利润为负)。
    • 第一天未持有股票且未处于冷却期:rest[0] = 0
    • 第一天处于冷却期:cooldown[0] = 0(不可能在第一天卖出股票)。
  5. 最终结果

    • 在最后一天,手里不持有股票的最大利润可以是:
      1. 处于冷却期:cooldown[-1]
      2. 处于休息状态:rest[-1]
    • 返回: [ \max(cooldown[-1], rest[-1]) ]

算法实现

以下是 Python 实现代码:

def solution(stocks):
    n = len(stocks)
    if n == 0:
        return 0

    # 初始化状态
    hold = [0] * n
    cooldown = [0] * n
    rest = [0] * n

    # 初始条件
    hold[0] = -stocks[0]
    cooldown[0] = 0
    rest[0] = 0

    # 状态转移
    for i in range(1, n):
        hold[i] = max(hold[i - 1], rest[i - 1] - stocks[i])
        cooldown[i] = hold[i - 1] + stocks[i]
        rest[i] = max(rest[i - 1], cooldown[i - 1])

    # 返回最后一天的最大利润
    return max(cooldown[-1], rest[-1])

时间与空间复杂度

  1. 时间复杂度:(O(n))
    • 只需单次遍历数组。
  2. 空间复杂度:(O(n))
    • 使用了三个长度为 (n) 的辅助数组。