问题描述
小R近期表现出色,公司决定以股票的形式给予奖励,并允许他在市场上进行交易以最大化收益。给定一个数组,数组中的第 i 个元素代表第 i 天的股票价格。小R需要设计一个算法来实现最大利润。
股票交易规则如下:
- 小R可以多次买卖股票,但在买入新的股票前必须卖出之前的股票。
- 每次卖出股票后存在一天的冷冻期,在冷冻期内小R不能购买股票。
你的任务是帮助小R计算出在遵守交易规则的情况下能够获得的最大利润。
stocks: 一个整数列表,表示连续几天内的股票价格。 思路分析
这道题目要求设计一个算法来最大化股票交易的利润,具有以下特点:
- 交易规则:可以多次买入和卖出,但卖出后必须有一天的冷却期,期间不能再次买入。
- 目标:在整个交易过程中,获取的总利润最大化。
- 限制条件:每次买入需要卖出才能再买入,不能同时持有多个股票。
为了解决这个问题,我们可以使用动态规划(DP)来实现。动态规划的核心是将复杂问题分解为多个子问题,并通过递推公式高效地解决。
核心思想
动态规划通过定义状态来跟踪每天的决策和对应的最大利润。本题可以用三种状态来表示:
hold[i]:第 ( i ) 天手里持有股票时的最大利润。cooldown[i]:第 ( i ) 天刚卖出股票(处于冷却期)的最大利润。rest[i]:第 ( i ) 天未持有股票,且没有处于冷却期的最大利润。
每个状态都有对应的递推公式,这些公式用来更新每天的最大利润。
状态转移方程
-
hold[i]:- 第 ( i ) 天持有股票的最大利润有两种可能:
- 第 ( i-1 ) 天已经持有股票,不进行任何操作,利润为
hold[i-1]。 - 第 ( i-1 ) 天未持有股票且不处于冷却期,今天买入股票,利润为
rest[i-1] - stocks[i]。
- 第 ( i-1 ) 天已经持有股票,不进行任何操作,利润为
- 状态转移方程: [ hold[i] = \max(hold[i-1], rest[i-1] - stocks[i]) ]
- 第 ( i ) 天持有股票的最大利润有两种可能:
-
cooldown[i]:- 第 ( i ) 天处于冷却期的最大利润,只有一种可能:
- 第 ( i-1 ) 天持有股票,并在今天卖出股票,利润为
hold[i-1] + stocks[i]。
- 第 ( i-1 ) 天持有股票,并在今天卖出股票,利润为
- 状态转移方程: [ cooldown[i] = hold[i-1] + stocks[i] ]
- 第 ( i ) 天处于冷却期的最大利润,只有一种可能:
-
rest[i]:- 第 ( i ) 天未持有股票且不处于冷却期的最大利润有两种可能:
- 第 ( i-1 ) 天也处于休息状态,利润为
rest[i-1]。 - 第 ( i-1 ) 天处于冷却期,利润为
cooldown[i-1]。
- 第 ( i-1 ) 天也处于休息状态,利润为
- 状态转移方程: [ rest[i] = \max(rest[i-1], cooldown[i-1]) ]
- 第 ( i ) 天未持有股票且不处于冷却期的最大利润有两种可能:
-
初始条件:
- 第一天持有股票:
hold[0] = -stocks[0](买入股票,利润为负)。 - 第一天未持有股票且未处于冷却期:
rest[0] = 0。 - 第一天处于冷却期:
cooldown[0] = 0(不可能在第一天卖出股票)。
- 第一天持有股票:
-
最终结果:
- 在最后一天,手里不持有股票的最大利润可以是:
- 处于冷却期:
cooldown[-1]。 - 处于休息状态:
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])
时间与空间复杂度
- 时间复杂度:(O(n))
- 只需单次遍历数组。
- 空间复杂度:(O(n))
- 使用了三个长度为 (n) 的辅助数组。