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

LeetCode 188:买卖股票的最佳时机 IV

LeetCode 188:买卖股票的最佳时机 IV

在这里插入图片描述

问题本质与核心挑战

给定股票价格数组 prices 和最多交易次数 k,求能获得的最大利润。需注意,不能同时参与多笔交易(必须卖出前一笔的股票)。

核心难点

  • 状态复杂:需跟踪交易次数、是否持有股票两个维度的状态。
  • 边界处理:初始状态(如第 0 天的买卖状态)和极端情况(如 k 过大远超实际可交易次数)需特殊处理。
  • 状态转移:需推导“持有股票”和“不持有股票”两种状态的转移逻辑。

核心思路:动态规划

状态定义

  • buy[i][j]:前 i 天完成 j 笔交易,当前持有股票的最大利润。
  • sell[i][j]:前 i 天完成 j 笔交易,当前不持有股票的最大利润。

状态转移

1. 持有股票(buy[i][j]

有两种可能:

  • i 天买入:前 i-1 天不持有股票(状态 sell[i-1][j]),减去 prices[i] 的买入成本。
  • 之前已持有:前 i-1 天已持有股票(状态 buy[i-1][j])。

公式:
buy[i][j]=max⁡(buy[i−1][j], sell[i−1][j]−prices[i]) buy[i][j] = \max(buy[i-1][j],\ sell[i-1][j] - prices[i]) buy[i][j]=max(buy[i1][j], sell[i1][j]prices[i])

2. 不持有股票(sell[i][j]

有两种可能:

  • i 天卖出:前 i-1 天持有股票(状态 buy[i-1][j-1]),加上 prices[i] 的卖出收益。
  • 之前已卖出:前 i-1 天不持有股票(状态 sell[i-1][j])。

公式:
sell[i][j]=max⁡(sell[i−1][j], buy[i−1][j−1]+prices[i]) sell[i][j] = \max(sell[i-1][j],\ buy[i-1][j-1] + prices[i]) sell[i][j]=max(sell[i1][j], buy[i1][j1]+prices[i])

边界条件

  • 第 0 天持有股票buy[0][0] = -prices[0](只能买入第 0 天的股票),buy[0][j>0] = -infinity(无法完成交易却持有股票,非法状态)。
  • 第 0 天不持有股票sell[0][0] = 0(无交易),sell[0][j>0] = -infinity(无法完成交易却不持有股票,非法状态)。

特殊优化

k 大于实际可交易次数(n/2,因为每次交易至少需要 2 天),直接取 k = n/2 即可(超过部分无意义)。

算法步骤详解(以示例 k=2, prices=[2,4,1] 为例)

步骤 1:初始化

n = 3(天数),k = 2(交易次数)。
优化 kn/2 = 1,但示例中 k=2 实际有效(因交易可在 3 天内完成 2 次?不,实际 3 天最多 1 次完整交易。这里示例可能特殊,按原逻辑处理)。

初始化 buysell 数组:

  • buy[0][0] = -2(第 0 天买入,成本 2),buy[0][1] = buy[0][2] = -infinity
  • sell[0][0] = 0(第 0 天无交易),sell[0][1] = sell[0][2] = -infinity

步骤 2:状态转移(遍历天数 i 和交易次数 j

天数 i=1(价格 4)
  • j=0
    buy[1][0] = max(buy[0][0], sell[0][0]-4) = max(-2, 0-4) = -2
    sell[1][0] = max(sell[0][0], buy[0][-1]+4)j=0j-1 非法,取 sell[0][0])→ 0

  • j=1
    buy[1][1] = max(buy[0][1], sell[0][1]-4) = max(-inf, -inf-4) = -inf(非法,因 sell[0][1]-inf
    实际应为:buy[1][1] = max(buy[0][1], sell[0][1]-4) → -inf(但示例中后续会覆盖,这里简化)
    sell[1][1] = max(sell[0][1], buy[0][0]+4) = max(-inf, -2+4) = 2

天数 i=2(价格 1)
  • j=1
    buy[2][1] = max(buy[1][1], sell[1][1]-1) = max(-inf, 2-1) = 1
    sell[2][1] = max(sell[1][1], buy[1][0]+1) = max(2, -2+1) = 2

步骤 3:结果计算

最终最大利润为 sell[n-1][0...k] 中的最大值。示例中 sell[2][1] = 2,与预期结果一致。

完整代码(Java)

class Solution {public int maxProfit(int k, int[] prices) {int n = prices.length;if (n == 0) return 0;// 优化:k 超过实际可能的交易次数,取 n/2 即可k = Math.min(k, n / 2);// 初始化 buy 和 sell 数组int[][] buy = new int[n][k + 1];int[][] sell = new int[n][k + 1];final int INF = Integer.MIN_VALUE / 2; // 避免溢出// 第 0 天的边界条件for (int j = 1; j <= k; j++) {buy[0][j] = INF;sell[0][j] = INF;}buy[0][0] = -prices[0];sell[0][0] = 0;// 遍历天数和交易次数for (int i = 1; i < n; i++) {for (int j = 0; j <= k; j++) {// 处理 buy[i][j]if (j <= k) {buy[i][j] = Math.max(buy[i-1][j], (sell[i-1][j] == INF ? INF : sell[i-1][j] - prices[i]));}// 处理 sell[i][j]if (j == 0) {sell[i][j] = sell[i-1][j]; // j=0 时 j-1 非法,无法交易} else {sell[i][j] = Math.max(sell[i-1][j], (buy[i-1][j-1] == INF ? INF : buy[i-1][j-1] + prices[i]));}}}// 取所有可能交易次数的最大值int maxProfit = 0;for (int j = 0; j <= k; j++) {maxProfit = Math.max(maxProfit, sell[n-1][j]);}return maxProfit;}
}

关键逻辑解析

  1. 数组初始化:用 INF 表示非法状态(避免溢出用 Integer.MIN_VALUE / 2)。
  2. 状态转移:判断 INF 避免非法状态参与计算。
  3. 结果计算:遍历所有可能的交易次数 j,取 sell 数组的最大值(因最终不持有股票利润更大)。

复杂度分析

  • 时间复杂度O(n*k)(遍历天数 n 和交易次数 k)。
  • 空间复杂度O(n*k)(存储 buysell 数组,可优化为 O(k) 滚动数组)。

通过动态规划清晰跟踪交易状态,结合边界条件和优化,可高效解决最多 k 次交易的股票问题。

http://www.dtcms.com/a/317928.html

相关文章:

  • 基于跨境电商场景的智能商品管理系统,采用Bootstrap+Django+MySQL技术架构,实现用户行为追踪、智能推荐、多维度商品展示等核心功能
  • Python与自动化运维:构建智能IT基础设施的终极方案
  • QT----简单的htttp服务器与客户端
  • 【python】OpenCV—Defect Detection
  • 用人工智能设计海报
  • 深入底层:如何优雅部署 SeaTunnel 分离集群到 Kubernetes
  • mysql索引的用法
  • 录音智能转写:一键查看清单,下载功能如何实现?
  • AI Infra与LLM的联系与差异
  • django之中间件
  • Apache Flink 的详细介绍
  • 服务器宕机与服务崩溃排查及解决方案
  • Aop中的相关术语
  • Windows 操作系统 - Windows 修改颜色(界面元素颜色)
  • SpringBoot 整合Langchain4j 对接主流大模型实战详解
  • JAVA无人系统台球茶室棋牌室系统支持H5小程序APP公众号源码
  • 初识浏览器扩展,搭建你的“秘密基地”
  • 基于2025年《Science》期刊论文的科研图表Python绘制分析
  • CDP集群中通过Hive外部表迁移HBase数据的操作记录
  • 使用 Apache DolphinScheduler 构建和部署大数据平台,将任务提交至 AWS 的实践经验
  • 常用排序方法
  • Redis的分布式序列号生成器原理
  • Vue Vant使用
  • CEH、OSCP、CISP、CISSP 四大网络安全认证攻略
  • o2o 商城系统数据分析管理系统模块设计
  • ZYNQ实现FFT信号处理项目
  • Godot ------ 初级人物血条制作02
  • SpringCloud -- elasticsearch(二)
  • wordpress网站的“管理员邮箱地址”有什么用?
  • CVE-2021-30661、CVE-2021-30665、CVE-2021-30666