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

75 阅读5分钟

问题描述

小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

样例4:

输入:stocks = [2, 3, 4, 5, 6, 7]
输出:5

样例5:

输入:stocks = [1, 6, 2, 7, 13, 2, 8]
输出:12

  1. 状态定义

    • hold[i]:表示第 i 天持有股票时的最大利润。
    • sold[i]:表示第 i 天卖出股票后的最大利润。
    • rest[i]:表示第 i 天处于冷冻期(即前一天卖出股票)时的最大利润。
  2. 状态转移

    • hold[i] 可以从 hold[i-1](前一天持有股票)或者 rest[i-1] - stocks[i](前一天处于冷冻期,今天买入股票)转移而来。
    • sold[i] 只能从 hold[i-1] + stocks[i](前一天持有股票,今天卖出)转移而来。
    • rest[i] 可以从 rest[i-1](前一天处于冷冻期)或者 sold[i-1](前一天卖出股票)转移而来。
  3. 初始状态

    • hold[0] 初始化为 -stocks[0](第一天买入股票)。
    • sold[0]rest[0] 初始化为 0
  4. 最终结果

    • 最终的最大利润应该是 sold[n-1]rest[n-1] 中的最大值,因为最后一天可能处于冷冻期或者卖出股票。

根据以上思路,我们可以开始编写代码。以下是代码框架:

public class Main {
    public static int solution(int[] stocks) {
        if (stocks == null || stocks.length == 0) {
            return 0;
        }
        
        int n = stocks.length;
        int[] hold = new int[n];
        int[] sold = new int[n];
        int[] rest = new int[n];
        
        // 初始化状态
        hold[0] = -stocks[0];
        sold[0] = 0;
        rest[0] = 0;
        
        // 状态转移
        for (int i = 1; i < n; i++) {
            hold[i] = Math.max(hold[i-1], rest[i-1] - stocks[i]);
            sold[i] = hold[i-1] + stocks[i];
            rest[i] = Math.max(rest[i-1], sold[i-1]);
        }
        
        // 最终结果
        return Math.max(sold[n-1], rest[n-1]);
    }

    public static void main(String[] args) {
        // You can add more test cases here
        System.out.println(solution(new int[]{1, 2}) == 1);
        System.out.println(solution(new int[]{2, 1}) == 0);
        System.out.println(solution(new int[]{1, 2, 3, 0, 2}) == 3);
        System.out.println(solution(new int[]{2, 3, 4, 5, 6, 7}) == 5);
        System.out.println(solution(new int[]{1, 6, 2, 7, 13, 2, 8}) == 12);
    }
}

代码解释:

  • hold[i] 表示第 i 天持有股票时的最大利润。
  • sold[i] 表示第 i 天卖出股票后的最大利润。
  • rest[i] 表示第 i 天处于冷冻期时的最大利润。
  • 通过状态转移方程,我们逐步更新这些状态数组,最终得到最大利润。

1. 动态规划(Dynamic Programming)

动态规划是解决本题的核心方法。通过定义状态和状态转移方程,我们可以逐步计算出最优解。

  • 状态定义

    • hold[i]:表示第 i 天持有股票时的最大利润。
    • sold[i]:表示第 i 天卖出股票后的最大利润。
    • rest[i]:表示第 i 天处于冷冻期时的最大利润。
  • 状态转移方程

    • hold[i] = max(hold[i-1], rest[i-1] - stocks[i]):第 i 天持有股票的最大利润可以从第 i-1 天持有股票的状态转移而来,或者从第 i-1 天处于冷冻期并买入股票的状态转移而来。
    • sold[i] = hold[i-1] + stocks[i]:第 i 天卖出股票的最大利润只能从第 i-1 天持有股票并卖出股票的状态转移而来。
    • rest[i] = max(rest[i-1], sold[i-1]):第 i 天处于冷冻期的最大利润可以从第 i-1 天处于冷冻期的状态转移而来,或者从第 i-1 天卖出股票的状态转移而来。

2. 状态初始化

在动态规划中,初始状态的定义非常重要。本题中:

  • hold[0] = -stocks[0]:第一天买入股票的最大利润。
  • sold[0] = 0:第一天卖出股票的最大利润(实际上不可能,因为第一天无法卖出)。
  • rest[0] = 0:第一天处于冷冻期的最大利润。

3. 状态更新

通过循环遍历每一天的股票价格,根据状态转移方程更新 holdsoldrest 数组。

4. 最终结果

最终的最大利润应该是 sold[n-1]rest[n-1] 中的最大值,因为最后一天可能处于冷冻期或者卖出股票。

5. 时间复杂度和空间复杂度

  • 时间复杂度O(n),其中 n 是股票价格数组的长度。我们只需要遍历一次数组。
  • 空间复杂度O(n),因为我们使用了三个长度为 n 的数组来存储状态。

总结

本题通过动态规划的方法,定义了三个状态数组来表示不同状态下的最大利润,并通过状态转移方程逐步更新这些状态,最终得到最大利润。动态规划的核心思想是将复杂问题分解为子问题,并通过存储子问题的解来避免重复计算,从而提高效率。