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

128 阅读5分钟

题目解析

在股票交易问题中,我们的目标是设计一个算法,帮助小R在遵守交易规则的情况下,获得最大利润。规则如下:

  1. 小R可以多次买卖股票,但在买入新的股票前,必须卖出之前的股票。
  2. 每次卖出股票后,存在一个冷冻期,意味着在冷冻期内不能买入新的股票。

我们需要处理的核心是如何在多次买卖中避免冷冻期的影响,并同时计算出在这些约束条件下,如何最大化收益。

思路分析

为了最大化利润,我们可以采用动态规划的思想来求解这个问题。具体来说,我们可以用两个状态数组 holdcash 来分别记录在某一天结束时的状态:

  1. hold[i]:表示第 i 天结束时,持有股票的最大利润。
  2. cash[i]:表示第 i 天结束时,不持有股票的最大利润。

对于 hold[i],有两种可能的状态:

  • 前一天已经持有股票:那么今天继续持有,利润保持不变。
  • 前天没有持有股票,并且在前前一天卖掉股票后今天重新购买股票,那么今天的利润会减去今天的股票价格。

对于 cash[i],也有两种可能的状态:

  • 前一天已经不持有股票,今天继续不持有,利润保持不变。
  • 前一天持有股票,在今天卖出股票,利润会增加今天的股票价格。

动态规划状态转移方程

  • hold[i] = max(hold[i - 1], cash[i - 2] - stocks[i]):表示第 i 天持有股票的最大利润。可以从前一天持有股票继续持有,也可以从两天前没有股票的状态中,今天购买股票。
  • cash[i] = max(cash[i - 1], hold[i - 1] + stocks[i]):表示第 i 天不持有股票的最大利润。可以从前一天不持有股票继续不持有,或者从前一天持有股票并在今天卖出。

初始状态:

  • 第一天持有股票的利润为 -stocks[0],即买入股票花费了价格。
  • 第一天不持有股票的利润为 0

代码详解

def solution(stocks):
    n = len(stocks)
    
    # 初始化两个状态数组
    hold = [0] * n  # hold[i] 表示第 i 天结束时持有股票的最大利润
    cash = [0] * n  # cash[i] 表示第 i 天结束时不持有股票的最大利润
    
    # 第一天的初始化
    hold[0] = -stocks[0]  # 第一天买入股票,花费股票价格
    cash[0] = 0            # 第一天不买股票,利润为 0
    
    for i in range(1, n):
        if i >= 2:
            # 当前持有股票的最大利润:保持前一天的状态,或者在两天前不持有股票并在今天买入
            hold[i] = max(hold[i - 1], cash[i - 2] - stocks[i])
        else:
            # 第二天持有股票的最大利润:保持前一天的状态,或者第二天买入股票
            hold[i] = max(hold[i - 1], -stocks[i])
        
        # 当前不持有股票的最大利润:保持前一天的状态,或者卖掉股票
        cash[i] = max(cash[i - 1], hold[i - 1] + stocks[i])
    
    return cash[-1]  # 返回最后一天不持有股票时的最大利润

if __name__ == "__main__":
    print(solution([1, 2]) == 1 )  # 输出 1
    print(solution([2, 1]) == 0 )  # 输出 0
    print(solution([1, 2, 3, 0, 2]) == 3 )  # 输出 3
    print(solution([2, 3, 4, 5, 6, 7]) == 5 )  # 输出 5
    print(solution([1, 6, 2, 7, 13, 2, 8]) == 12 )  # 输出 12

代码分析

  1. 初始化

    • hold[0] = -stocks[0],表示第一天买入股票,获得的利润是负的,因为购买股票需要支付资金。
    • cash[0] = 0,表示第一天没有交易,利润为0。
  2. 动态规划递推

    • hold[i] = max(hold[i - 1], cash[i - 2] - stocks[i]):这里通过对比是否选择在 i 天买入股票(cash[i-2] - stocks[i])或者保持前一天持有的状态来决定。
    • cash[i] = max(cash[i - 1], hold[i - 1] + stocks[i]):通过对比是否选择在 i 天卖出股票(hold[i-1] + stocks[i])来计算不持有股票时的最大利润。
  3. 返回结果

    • 最终结果为 cash[-1],即最后一天没有持有股票时的最大利润。

知识总结

在刷题的过程中,我学到了如何通过动态规划来解决类似于股票交易类的问题。动态规划通过引入状态数组来记录某一时刻的最佳选择,避免了重复计算,并有效地降低了时间复杂度。此类问题通常会涉及到以下几个方面:

  1. 状态定义:我们需要明确状态表示什么,通常是关于时间和行为的组合。例如,hold[i] 表示第 i 天持有股票的最大利润,cash[i] 表示不持有股票的最大利润。
  2. 状态转移方程:如何通过当前的状态推导出下一个状态,这涉及到多个选择的对比。
  3. 边界条件:对于初始状态的处理,确保递推过程不出错。

对于其他入门同学的建议是:

  • 在处理动态规划问题时,首先需要明确状态的定义,并尽量将状态转移方程写清楚。
  • 不要忽视边界条件,特别是在数组和索引涉及到时,初学者容易在这些细节上出错。
  • 多做题,积累经验,理解每道题背后的思路和规律。

总结

本题是一个典型的动态规划问题,利用 holdcash 两个状态数组,模拟股票买卖过程中的最大利润。通过明确的状态转移方程和合理的初始状态设置,最终得到了正确的结果。对于类似的股票交易问题,可以通过动态规划来高效求解,并通过分析状态的转换关系来设计合适的算法。