news 2026/4/20 21:07:56

LeetCode 123:Best Time to Buy and Sell Stock III 三维DP完全解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
LeetCode 123:Best Time to Buy and Sell Stock III 三维DP完全解析

题目与约束

给定 prices,prices[i] 是第 i 天的股价。

最多完成 2 次「买入 + 卖出」交易。

不能同时持有多笔仓位:必须先卖掉才能再买。

目标是最大利润,可以是 0。

这类题的本质是:在时间线上做一系列「买 / 卖 / 不动」决策,并受到「次数上限」和「持仓状态」限制,非常适合建状态机 + DP。

三维 DP 状态设计

最通用、教科书式的状态是三维 dp[i][j][k]:labuladong+1​

  • i:天数下标,0…n-1,对应 prices[i]。
  • j:还能完成的「卖出」次数(交易次数),这里最多 2,所以 j∈{0,1,2}。leetcode​
  • k:当前是否持股:
    • k=0:不持股;
    • k=1:持股。

定义:

  • dp[i][j][0]:第 i 天结束时,不持股,之后还可以做 j 次卖出的最大利润。
  • dp[i][j][1]:第 i 天结束时,持股,之后还可以做 j 次卖出的最大利润。leetcode​

用「还能卖 j 次」的好处是:卖出时很自然写成「从 j+1 转移到 j」,表达“卖出消耗一次交易”的意思。

状态转移公式

设今天是第 i 天,价格 price = prices[i]。

1)今天结束时不持股(k=0):

两种可能:

  • 昨天也不持股,今天不操作:
    dp[i-1][j][0]

  • 昨天持股,今天卖出,消耗一次卖出机会:
    dp[i-1][j+1][1] + priceleetcode​

所以:

dp[i][j][0] = max(dp[i-1][j][0], dp[i-1][j+1][1] + price)

注意:只有在 j+1≤2 时,第二项才有效,否则不存在 dp[i-1][j+1],这时直接视为「不可能」,不会取。leetcode​

2)今天结束时持股(k=1):

两种可能:

  • 昨天就持股,今天不操作:
    dp[i-1][j][1]leetcode​

  • 昨天不持股,今天买入,不消耗卖出次数:
    dp[i-1][j][0] − price

所以:

dp[i][j][1] = max(dp[i-1][j][1], dp[i-1][j][0] - price)

这两条就完整刻画了「不持股 / 持股」两种状态在时间上的演化。

边界与初始化

时间边界 i=0 单独处理:

  • **第 0 天不持股:**利润为 0。

    • 对所有 j:dp[0][j][0] = 0
  • **第 0 天持股:**等价于第 0 天买入一股。

    • 对 j≥1:dp[0][j][1] = -prices[0]。leetcode​

对于 j=0(之后不能再卖):

  • dp[i][0][0]:不持股,已经不能再卖,利润就是「之前已经赚到的」,在本题中可以安全设为 0 的下界。

  • dp[i][0][1]:手里有股票但永远不能卖,这种状态在逻辑上是无效的,应该设为一个非常小的负数(负无穷),保证后续 max 时永远不会选到。leetcode​

代码里通常用一个常量 NEG_INF 来代表「不可能的状态」,比如 -1e9:

#defineNEG_INF-1000000000

三维 DP 的 C 代码实现

下面是完整的 C 代码,用三维数组 dp[i][j][k] 实现「最多两次交易」:geeksforgeeks+1​

#include<stdio.h>#defineMAX(a,b)((a)>(b)?(a):(b))#defineMAXN100000#defineNEG_INF-1000000000intmaxProfit(int*prices,intpricesSize){if(pricesSize==0)return0;intn=pricesSize;intK=2;// 最多 2 次交易(卖出)// dp[i][j][k]:// i: 第 i 天 (0..n-1)// j: 还能完成的卖出次数 (0..K)// k: 是否持股 (0 不持股, 1 持股)staticintdp[MAXN][3][2];// 初始化第 0 天for(intj=0;j<=K;++j){dp[0][j][0]=0;// 第 0 天不持股,利润为 0dp[0][j][1]=-prices[0];// 第 0 天买入一股}// 还能卖 0 次但持股:无效状态dp[0][0][1]=NEG_INF;// 状态转移:i 从 1 开始,因为 i=0 已经手动初始化好for(inti=1;i<n;++i){for(intj=0;j<=K;++j){intprice=prices[i];// 1. 不持股:max(昨天不持股, 昨天持股今天卖)intstay_no_stock=dp[i-1][j][0];intsell_today=NEG_INF;if(j+1<=K){sell_today=dp[i-1][j+1][1]+price;}dp[i][j][0]=MAX(stay_no_stock,sell_today);// 2. 持股:max(昨天持股, 昨天不持股今天买)intstay_stock=dp[i-1][j][1];intbuy_today=dp[i-1][j][0]-price;dp[i][j][1]=MAX(stay_stock,buy_today);}// 还能卖 0 次但持股仍然无效dp[i][0][1]=NEG_INF;}// 最多 2 次交易,最后一天不持股的最大利润intans=dp[n-1][2][0];// 本题允许 0 利润,防止 ans 为负数时返回负值returnans<0?0:ans;}

细节解释:

  1. i 从 1 开始循环,是因为 i=0 那一行已经手动初始化,转移都从 i-1 来,避免出现 dp[-1][…] 越界。

  2. sell_today 初值设为 NEG_INF,表示「默认卖出这条路走不通」,只有在 j+1 <= K 且前一状态有效时才更新。

  3. 当 j=2 时,j+1=3>K,就没有「还能卖 3 次」这个状态,所以不能通过「卖出」到达 dp[i][2][0],只能从「昨天不持股、还能卖 2 次」继承。

与 4 个一维状态的等价关系

三维 DP 是最清晰的「教科书版本」,但这题最多只允许 2 次交易,可以进一步压缩成 4 个一维状态:algo+1​

  • buy1:做完「第一次买入」后的最大利润(持股)。
  • sell1:做完「第一次卖出」后的最大利润(不持股)。
  • buy2:做完「第二次买入」后的最大利润(持股)。
  • sell2:做完「第二次卖出」后的最大利润(不持股)。

对每一天的 price:

buy1=max(buy1,-price);// 第一次买sell1=max(sell1,buy1+price);// 第一次卖buy2=max(buy2,sell1-price);// 第二次买sell2=max(sell2,buy2+price);// 第二次卖

这 4 个状态可以理解为把三维 dp[i][j][k] 中真正会被用到的那几类状态抽出来,省去了显式的 i 维和 j 维,从而把空间压缩到 O(1)。codeanddebug+1​

小结:思维路径

  1. 先用三维 dp[i][j][k] 把「时间 / 交易次数 / 持仓状态」都写清楚。

  2. 写出两条核心转移:

    • **不持股:**max(昨天不持股, 昨天持股今天卖)。
    • **持股:**max(昨天持股, 昨天不持股今天买)。
  3. 处理好边界:

    • i=0 单独初始化;
    • j=0 的持股设为负无穷。
  4. 理解以后,再把只用到的状态压缩成 4 个一维变量,写成常见的 buy1/sell1/buy2/sell2 解法。

这一整套就是「通用股票 DP 模板」在 LeetCode 123 上的完整展开版,用它可以推广到「k 次交易」「冷冻期」「手续费」等变种。takeuforward+1​

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/17 22:35:00

视频配音总不同步?IndexTTS 2.0自回归架构实现精准时长对齐

视频配音总不同步&#xff1f;IndexTTS 2.0自回归架构实现精准时长对齐 在短视频、动画二创和虚拟主播内容爆发的今天&#xff0c;一个常被忽视却极其影响观感的问题浮出水面&#xff1a;语音和画面总是对不上。你精心剪辑的画面节奏刚到高潮&#xff0c;AI生成的配音却拖了半拍…

作者头像 李华
网站建设 2026/4/17 22:21:34

FFXIV TexTools终极指南:快速掌握游戏外观自定义完整流程

FFXIV TexTools终极指南&#xff1a;快速掌握游戏外观自定义完整流程 【免费下载链接】FFXIV_TexTools_UI 项目地址: https://gitcode.com/gh_mirrors/ff/FFXIV_TexTools_UI 想要让你的《最终幻想14》角色与众不同吗&#xff1f;FFXIV TexTools作为一款强大的游戏模组管…

作者头像 李华
网站建设 2026/4/18 17:26:23

快速上手WeChatFerry:2025微信机器人实战开发指南

快速上手WeChatFerry&#xff1a;2025微信机器人实战开发指南 【免费下载链接】WeChatFerry 微信逆向&#xff0c;微信机器人&#xff0c;可接入 ChatGPT、ChatGLM、讯飞星火、Tigerbot等大模型。Hook WeChat. 项目地址: https://gitcode.com/GitHub_Trending/we/WeChatFerry…

作者头像 李华
网站建设 2026/4/16 9:57:19

2026年我国网络安全发展趋势预测

【收藏必学】2026年网络安全趋势全景图&#xff1a;AI攻防、零信任与深度伪造技术深度解析 文章分析了2026年中国网络安全七大趋势&#xff1a;AI自主威胁崛起、身份安全成为核心攻击面、深度伪造信任危机、勒索软件多阶段攻击升级、政策技术驱动安全深化、市场服务化转型、安…

作者头像 李华
网站建设 2026/4/17 16:16:17

Windows HEIC缩略图扩展:三步解决苹果照片预览难题

Windows HEIC缩略图扩展&#xff1a;三步解决苹果照片预览难题 【免费下载链接】windows-heic-thumbnails Enable Windows Explorer to display thumbnails for HEIC files 项目地址: https://gitcode.com/gh_mirrors/wi/windows-heic-thumbnails 你是否曾经将iPhone拍摄…

作者头像 李华
网站建设 2026/4/16 9:57:20

HTML页面嵌入IndexTTS 2.0生成的音频实现交互式阅读体验

HTML页面嵌入IndexTTS 2.0生成的音频实现交互式阅读体验 在内容消费节奏日益加快的今天&#xff0c;用户早已不满足于“只看文字”。短视频、虚拟主播、AI配音等形态正在重塑信息传递的方式。尤其在教育、有声书、社交媒体等领域&#xff0c;一个能“说话”的网页&#xff0c;…

作者头像 李华