当前位置: 首页 > article >正文

【动态规划】股票市场交易策略优化

文章目录

      • 一、问题描述
      • 二、解决思路
        • 状态转移
        • 初始化
        • 最终结果
      • 三、代码实现
      • 执行流程解析
      • 时间和空间复杂度

一、问题描述

我们要解决的是一个关于股票买卖的问题:给定一个股票价格数组 stocks,每一天的价格为数组中的一个元素。我们可以通过买入和卖出的操作来获取收益,但需要遵守以下规则:

  1. 每次买入前,必须先卖出之前的股票(即不能同时持有两次未卖出的股票)。
  2. 卖出股票后有一个冷冻期,也就是说,在卖出后的第二天才能继续买入股票。

我们的目标是:计算出在满足上述规则的情况下,最大可以获得的利润

例如,给定数组 [1, 2, 3, 0, 2]

  • 第一天买入,花费 -1
  • 第二天卖出,收入 +2
  • 第四天再次买入,花费 -0
  • 第五天卖出,收入 +2。 总收益为 3

二、解决思路

这是一个经典的 动态规划 问题。我们通过记录每一天的三种可能状态来逐步计算:

  1. 持有股票(hold):表示当天我们手中有股票的情况下,最大可能的收益。
  2. 未持有股票但不在冷冻期(unhold):表示当天我们手中没有股票,并且可以自由操作的情况下,最大可能的收益。
  3. 未持有股票且处于冷冻期(cooldown):表示当天我们手中没有股票,但因为刚卖出,处于冷冻期的情况下,最大可能的收益。
状态转移
  • 持有股票(hold

    • 要么昨天已经持有股票,今天保持不动(收益不变)。
    • 要么昨天没有股票(并且不在冷冻期),今天买入股票(收益减去今天的价格)。
    • 状态转移公式:在这里插入图片描述
  • 未持有股票但不在冷冻期(unhold

    • 要么昨天已经没有股票且不在冷冻期,今天也不操作(收益不变)。
    • 要么昨天刚结束冷冻期,今天自由操作(收益等于昨天冷冻期的收益)。
    • 状态转移公式:在这里插入图片描述
  • 未持有股票且处于冷冻期(cooldown

    • 必须是昨天持有股票,今天卖出进入冷冻期(收益增加今天的价格)。
    • 状态转移公式: 在这里插入图片描述
初始化
  • 第一天持有股票hold[0] = -stocks[0](买入股票后收益为负)。
  • 第一天未持有股票且不在冷冻期unhold[0] = 0(什么都不做,收益为 0)。
  • 第一天未持有股票且处于冷冻期cooldown[0] = 0(第一天不可能处于冷冻期)。
最终结果

最后一天的最大利润一定是:在这里插入图片描述

因为只有未持有股票时,收益才可能是最大值。


三、代码实现

public class Main {
    public static int solution(int[] stocks) {
        if (stocks == null || stocks.length == 0) {
            return 0; // 没有数据时,最大收益为 0
        }

        // 初始化第 1 天的三种状态
        int hold = -stocks[0];      // 第一天买入股票,收益为负的价格
        int unhold = 0;            // 第一天不持有股票,收益为 0
        int cooldown = 0;          // 第一天冷冻期不可能发生,收益为 0

        // 从第 2 天开始计算
        for (int i = 1; i < stocks.length; i++) {
            // 暂存之前的状态值,用于计算
            int prevHold = hold;
            int prevUnhold = unhold;
            int prevCooldown = cooldown;

            // 更新持有股票状态
            hold = Math.max(prevHold, prevUnhold - stocks[i]);
            // 更新未持有股票且不在冷冻期状态
            unhold = Math.max(prevUnhold, prevCooldown);
            // 更新未持有股票且处于冷冻期状态
            cooldown = prevHold + stocks[i];
        }

        // 最终结果是未持有股票的两种状态的最大值
        return Math.max(unhold, cooldown);
    }

    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
    }
}

执行流程解析

以输入数组 [1, 2, 3, 0, 2] 为例,逐步计算各状态:

天数持有股票(hold)未持有股票且无冷冻期(unhold)未持有股票且冷冻期(cooldown)
1-100
2-101
3-112
412-1
5123

最终结果为:max(unhold[4], cooldown[4]) = 3


时间和空间复杂度

  1. 时间复杂度:每一天的计算是常数操作,时间复杂度为 O(n),其中 n 是数组的长度。
  2. 空间复杂度:只用到了常数个变量,空间复杂度为 O(1)。

我们通过动态规划,把问题分解为三个状态,分别计算每天的最佳选择。

博客


http://www.kler.cn/a/415897.html

相关文章:

  • 如何启动 Docker 服务:全面指南
  • Linux -初识 与基础指令1
  • FastAPI 跨域访问cors设置
  • 浅谈telnet和ping
  • NSSCTF web刷题
  • 面试——HashMap的并发问题
  • hhdb数据库介绍(10-17)
  • Kylin Server V10 下 Nacos 集群部署
  • KST-3D01型胎儿超声仿真体模、吸声材料以及超声骨密度仪用定量试件介绍
  • 总结UiPath Studio的介绍与安装步骤
  • DETR:End-to-End Object Detection with Transformers
  • Android触摸事件setOnTouchListener用法
  • 各个排序算法基础速通万字介绍
  • STM32--MAP文件
  • 【论文复现】LoRA:大模型的低阶自适用
  • Python-链表数据结构学习(1)
  • 10个Word自动化办公脚本
  • HCIA笔记6--路由基础
  • 信息系统项目管理-论文写作方法之背景二
  • 开源的跨平台SQL 编辑器Beekeeper Studio
  • pdf.js 预览pdf的时候发票数据缺失显示不全:字体加载出错(缺失)导致部分缺失
  • qt QGraphicsPolygonItem详解
  • RVO动态避障技术方案介绍
  • 力扣--LCR 150.彩灯装饰记录II
  • 深度学习2:从零开始掌握PyTorch:数据操作不再是难题
  • 从零开发操作系统-聊一聊C语言中的头文件