动态规划Day-2 股票市场交易策略优化 | 豆包MarsCode AI刷题

112 阅读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

样例4:

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

样例5:

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

 

 

问题理解

我们需要计算在给定的股票价格数组中,通过多次买卖股票并遵守冷冻期规则,能够获得的 最大利润

关键点

  1. 多次买卖:这意味着我们可以多次买入和卖出股票。
  2. 冷冻期: 每次卖出后需要等待一天才能再次买入。

数据结构与算法选择

由于我们需要考虑多次买卖和冷冻期,动态规划(DP) 是一个合适的选择。我们可以使用两个状态来表示每一天的状态:

  • hold[i] :表示第 i 天持有股票时的最大利润。
  • unhold[i] :表示第 i 天不持有股票时的最大利润。

状态转移方程

  1. 持有股票
    • 如果第 i 天持有股票,那么可能是前一天就持有股票,或者前一天不持有股票但今天买入。
    • hold[i] = max(hold[i-1], unhold[i-2] - stocks[i])
  2. 不持有股票
    • 如果第 i 天不持有股票,那么可能是前一天就不持有股票,或者前一天持有股票但今天卖出。
    • unhold[i] = max(unhold[i-1], hold[i-1] + stocks[i])

初始条件

  • hold[0] = -stocks[0] :第一天买入股票。
  • unhold[0] = 0:第一天不持有股票。

最终答案

最终的最大利润是不持有股票的最大值,即 unhold[n-1] ,其中 n 是股票价格数组的长度。

 

状态转移方程

我们有两个状态数组:

  • hold[i] :表示第 i 天持有股票时的最大利润。
  • unhold[i] :表示第 i 天不持有股票时的最大利润。

状态转移方程的详细解释

  1. 持有股票的状态转移
    • hold[i] = max(hold[i-1], unhold[i-2] - stocks[i])
    • 解释:
      • hold[i-1] :表示第 i 天继续持有前一天的股票。
      • unhold[i-2] - stocks[i] :表示第 i 天买入股票。由于有冷冻期,买入股票的前提是前两天不持有股票(即 unhold[i-2] )。
  2. 不持有股票的状态转移
    • unhold[i] = max(unhold[i-1], hold[i-1] + stocks[i])
    • 解释:
      • unhold[i-1] :表示第 i 天继续不持有股票。
      • hold[i-1] + stocks[i] :表示第 i 天卖出股票。卖出股票的前提是前一天持有股票(即 hold[i-1] )。

初始条件

  • hold[0] = -stocks[0] :第一天买入股票。
  • unhold[0] = 0:第一天不持有股票。

public class Main {

public static int solution(int[] stocks) {

        int n = stocks.length;

        if (n == 0) return 0;

 

        int[] hold = new int[n];

        int[] unhold = new int[n];

 

        // 初始条件

        hold[0] = -stocks[0];

        unhold[0] = 0;

 

        for (int i = 1; i < n; i++) {

            // 持有股票的状态转移

            hold[i] = Math.max(hold[i-1], (i >= 2 ? unhold[i-2] : 0) - stocks[i]);

            // 不持有股票的状态转移

            unhold[i] = Math.max(unhold[i-1], hold[i-1] + stocks[i]);

        }

 

        // 最终答案

        return unhold[n-1];

    }

 

    public static void main(String[] args) {

        // 测试用例

        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);

    }

}