股票市场交易策略优化 状态机DP | 豆包MarsCode AI 刷题

116 阅读3分钟

 问题描述

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

股票交易规则如下:

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

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

-   stocks: 一个整数列表,表示连续几天内的股票价格。

 测试样例

样例1:

 输入:stocks = [1, 2]  
输出:1

样例2:

 输入:stocks = [2, 1]  
输出:0

样例3:

 输入:stocks = [1, 2, 3, 0, 2]  
输出:3

 问题分析

对于这个问题,我们可以拆解为每一天发生了什么,而这样思考显然没有出于整体的思想,所以在思考时应当不仅仅考虑当前情况,还要考虑前几天的情况,比如在考虑第五天的利润,需要考虑的是第0至4天的利润加第五天的利润。需要注意的是,这里的利润指的是:

1.假设当天未买未卖,则利润为0。

2.假设当天卖了,则利润为stocks[i]。

3.假设当天买了,则利润为-stocks[i]。

我们定义dfs(i,0)表示第i天结束时,未持有股票的最大利润。

dfs(i,1)表示第i天结束时,持有股票的最大利润。

a123.png

图片来自b站:灵茶山艾府

 递归边界

dfs(-1,0)=0,第0天开始时未持有股票,利润为0
dfs(-1,1)=-inf ,第0天开始时不可能持有股票,是一个不合法的情况

 递归入口

dfs(i-1,0),因为最后一天结束时持有股票时不可能使利润最大化。

 冻结情况

冻结,也就是买入时前一天不能卖出股票,那么本来 dfs(i,1) = dfs(i-1,0)-stocks[i]可以直接转移至dfs(i,1) = dfs(i-2,0)-stocks[i]

 代码实现


-   时间复杂度O(n)
-   空间复杂度O(n)

 本题总结

1.  动态规划

    -   使用动态规划来解决这个问题,定义一个递归函数 f(i, hold, cooldown),表示在第 i 天,是否持有股票 (hold) 以及是否处于冷冻期 (cooldown) 时的最大利润。
-   i 表示当前天数,hold 表示是否持有股票,cooldown 表示是否处于冷冻期。

2.  状态转移

    -   如果 i < 0,表示天数无效,返回 0 或 -inf 取决于是否持有股票。
-   如果 cooldown 为 True,表示当前处于冷冻期,不能进行任何交易,直接返回 f(i-1, False, False)
-   如果 hold 为 True,表示当前持有股票,可以选择继续持有或卖出(卖出后进入冷冻期)。
-   如果 hold 为 False,表示当前不持有股票,可以选择继续不持有或买入(买入后持有股票)。

3.  缓存优化

    -   使用 functools.lru_cache 来缓存递归调用的结果,避免重复计算,提高效率。