news 2026/4/3 5:14:36

LeetCode 3573.买卖股票的最佳时机 V:深度优先搜索

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
LeetCode 3573.买卖股票的最佳时机 V:深度优先搜索

【LetMeFly】3573.买卖股票的最佳时机 V:深度优先搜索 / 动态规划:通俗讲解

力扣题目链接:https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-v/

给你一个整数数组prices,其中prices[i]是第i天股票的价格(美元),以及一个整数k

你最多可以进行k笔交易,每笔交易可以是以下任一类型:

  • 普通交易:在第i天买入,然后在之后的第j天卖出,其中i < j。你的利润是prices[j] - prices[i]

  • 做空交易:在第i天卖出,然后在之后的第j天买回,其中i < j。你的利润是prices[i] - prices[j]

注意:你必须在开始下一笔交易之前完成当前交易。此外,你不能在已经进行买入或卖出操作的同一天再次进行买入或卖出操作。

通过进行最多k笔交易,返回你可以获得的最大总利润。

示例 1:

输入:prices = [1,7,9,8,2], k = 2

输出:14

解释:

我们可以通过 2 笔交易获得 14 美元的利润:
  • 一笔普通交易:第 0 天以 1 美元买入,第 2 天以 9 美元卖出。
  • 一笔做空交易:第 3 天以 8 美元卖出,第 4 天以 2 美元买回。

示例 2:

输入:prices = [12,16,19,19,8,1,19,13,9], k = 3

输出:36

解释:

我们可以通过 3 笔交易获得 36 美元的利润:
  • 一笔普通交易:第 0 天以 12 美元买入,第 2 天以 19 美元卖出。
  • 一笔做空交易:第 3 天以 19 美元卖出,第 4 天以 8 美元买回。
  • 一笔普通交易:第 5 天以 1 美元买入,第 6 天以 19 美元卖出。

提示:

  • 2 <= prices.length <= 103
  • 1 <= prices[i] <= 109
  • 1 <= k <= prices.length / 2

自我评价:好文x1(bushi)

解题方法一:深度优先搜索

定义dfs(i, j, status)含义为:

  • 0到i ii天,共进行了j jj次买入或做空操作
  • status:0代表第i ii天要到没持有股票状态;1代表第i ii天要到手持股票的状态;2代表第i ii天要到做空的状态

假设买入或做空时立刻消耗交易次数(卖出或还上时交易完成不二次消耗次数),那么有:

  1. 如果status为0(这天结束后两清):可昨天本就两清今天什么都没干(dfs(i-1, j, 0)),可昨天是手持股票状态今天卖了(dfs(i-1, j, 1) + prices[i]),可昨天是空头状态今天买回来补上了(dfs(i-1, j, 2) - prices[i])。
  2. 如果status为1(这天结束后手持股票):可昨天本就持有股票今天什么都没干(dfs(i-1, j, 1)),可昨天两清今天刚买入(dfs(i-1, j-1, 0) - prices[i])。
  3. 如果status为2(这天结束后欠还股票):可昨天就是欠股票状态今天什么都没干(dfs(i-1, j, 2)),可昨天两清今天做空提前卖了股票(dfs(i-1, j-1, 0) + prices[i])。

边界条件:

  1. 可用操作次数始终不能为负,如果为负返回“负无穷”
  2. 天数为-1时(交易开始前)只能处于两清状态,如果交易开始前(i = − 1 i=-1i=1)状态已经处在持股或空头则说明状态不合法,返回“负无穷”。

时空复杂度:

  • 时间复杂度O ( l e n ( p r i c e s ) × k ) O(len(prices)\times k)O(len(prices)×k)
  • 空间复杂度O ( l e n ( p r i c e s ) × k ) O(len(prices)\times k)O(len(prices)×k)

AC代码

C++
/* * @LastEditTime: 2025-12-17 23:09:09 */typedeflonglongll;classSolution{private:vector<int>prices;unordered_map<int,ll>cache;inlineintgetKey(inti,intj,intstatus){returni*3000+j*3+status;}lldfs(inti,intj,intstatus){// 0~i天 最多交易j次// status: 0无1买2空头intkey=getKey(i,j,status);if(cache.count(key)){returncache[key];}if(j<0){return-1'000'000'000'000'000;}if(i<0){returnstatus?-1'000'000'000'000'000:0;}if(status==0){returncache[key]=max({dfs(i-1,j,0),dfs(i-1,j,1)+prices[i],dfs(i-1,j,2)-prices[i]});}elseif(status==1){returncache[key]=max(dfs(i-1,j-1,0)-prices[i],dfs(i-1,j,1));}else{returncache[key]=max(dfs(i-1,j-1,0)+prices[i],dfs(i-1,j,2));}}public:llmaximumProfit(vector<int>&prices,intk){this->prices=move(prices);returndfs(this->prices.size()-1,k,0);}};
Python

python记得最终返回结果前强制清空下缓存,虽然python也有gc机制但可能gc不及时导致MLE。

''' LastEditTime: 2025-12-17 23:18:54 '''fromtypingimportListfromfunctoolsimportcachefrommathimportinfclassSolution:defmaximumProfit(self,prices:List[int],k:int)->int:n=len(prices)@cachedefdfs(i:int,j:int,status:int)->int:"""0无1有2空头"""ifj<0:return-infifi<0:return-infifstatuselse0ifstatus==0:returnmax(dfs(i-1,j,0),dfs(i-1,j,1)+prices[i],dfs(i-1,j,2)-prices[i])elifstatus==1:returnmax(dfs(i-1,j,1),dfs(i-1,j-1,0)-prices[i])else:returnmax(dfs(i-1,j,2),dfs(i-1,j-1,0)+prices[i])ans=dfs(n-1,k,0)dfs.cache_clear()returnans

解题方法二:动态规划

将深度优先搜索翻译成递推:

ifstatus==0:returnmax(dfs(i-1,j,0),dfs(i-1,j,1)+prices[i],dfs(i-1,j,2)-prices[i])elifstatus==1:returnmax(dfs(i-1,j,1),dfs(i-1,j-1,0)-prices[i])else:returnmax(dfs(i-1,j,2),dfs(i-1,j-1,0)+prices[i])

翻译为:

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

注意为了防止下标出现-1可以令所有i在作dp下标时加上1:

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

时空复杂度:

  • 时间复杂度O ( l e n ( p r i c e s ) × k ) O(len(prices)\times k)O(len(prices)×k)
  • 空间复杂度O ( l e n ( p r i c e s ) × k ) O(len(prices)\times k)O(len(prices)×k)

AC代码

Python
''' LastEditTime: 2025-12-17 23:51:56 '''fromtypingimportListfrommathimportinfclassSolution:defmaximumProfit(self,prices:List[int],k:int)->int:n=len(prices)# dp[i][j][status]: i有效范围0~n-1,j有效范围0~k,这俩都多开一个无效状态的空间dp=[[[-inf]*3for_inrange(k+2)]for_inrange(n+1)]forjinrange(1,k+2):dp[0][j][0]=0fori,priceinenumerate(prices):forjinrange(1,k+2):dp[i+1][j][0]=max(dp[i][j][0],dp[i][j][1]+price,dp[i][j][2]-price)dp[i+1][j][1]=max(dp[i][j][1],dp[i][j-1][0]-price)dp[i+1][j][2]=max(dp[i][j][2],dp[i][j-1][0]+price)returndp[-1][-1][0]

解题方法三:动态规划+空间优化

不难发现第i ii天(dp[i+1][xx][x])数据仅和第i − 1 i-1i1天有关(dp[i][xx][x]),因此可以优化掉数组第一维。

注意j要倒序遍历,因为j依赖的是上一天的j-1,如果先更新j-1再更新j则会重复计算。

时空复杂度:

  • 时间复杂度O ( l e n ( p r i c e s ) × k ) O(len(prices)\times k)O(len(prices)×k)
  • 空间复杂度O ( k ) O(k)O(k)

AC代码

Python
''' LastEditTime: 2025-12-17 23:58:31 '''fromtypingimportListfrommathimportinfclassSolution:defmaximumProfit(self,prices:List[int],k:int)->int:n=len(prices)# dp[i][j][status]: i有效范围0~n-1,j有效范围0~k,这俩都多开一个无效状态的空间dp=[[-inf]*3for_inrange(k+2)]forjinrange(1,k+2):dp[j][0]=0fori,priceinenumerate(prices):forjinrange(k+1,0,-1):dp[j][0]=max(dp[j][0],dp[j][1]+price,dp[j][2]-price)dp[j][1]=max(dp[j][1],dp[j-1][0]-price)dp[j][2]=max(dp[j][2],dp[j-1][0]+price)returndp[-1][0]

同步发文于CSDN和我的个人博客,原创不易,转载经作者同意后请附上原文链接哦~

千篇源码题解已开源

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

GLM-4.5-FP8:重新定义大模型推理效率的突破性技术

GLM-4.5-FP8&#xff1a;重新定义大模型推理效率的突破性技术 【免费下载链接】GLM-4.5-FP8 项目地址: https://ai.gitcode.com/zai-org/GLM-4.5-FP8 从实际需求出发&#xff1a;企业面临的推理效率挑战 在当前大语言模型应用日益普及的背景下&#xff0c;企业普遍面临…

作者头像 李华
网站建设 2026/3/24 6:17:04

2026年Java面试题目收集整理归纳(持续更新)

我相信大多 Java 开发的程序员或多或少经历过 BAT 一些大厂的面试&#xff0c;也清楚一线互联网大厂 Java 面试是有一定难度的&#xff0c;小编经历过多次面试&#xff0c;有满意的也有备受打击的。因此呢小编想把自己这么多次面试经历以及近期的面试真题来个汇总分析&#xff…

作者头像 李华
网站建设 2026/4/1 22:08:30

一文搞懂ERP、MES的区别与联系

【ERP】和【MES】是制造业工厂经常会用到的两个系统。尽管二者在功能上有所交叉&#xff0c;但它们的设计定位、服务对象与运作层级存在明显差异&#xff0c;而要理解这些差异&#xff0c;正是企业实现高效管理与生产协同至关重要的一环。企业创办一个工厂&#xff0c;存在的目…

作者头像 李华
网站建设 2026/4/3 2:06:46

深度解析OctoSQL执行计划:从查询优化到性能调优实战指南

深度解析OctoSQL执行计划&#xff1a;从查询优化到性能调优实战指南 【免费下载链接】octosql octosql&#xff1a;这是一个SQL查询引擎&#xff0c;它允许您对存储在多个SQL数据库、NoSQL数据库和各种格式的文件中的数据编写标准SQL查询&#xff0c;尝试将尽可能多的工作压缩到…

作者头像 李华
网站建设 2026/3/27 23:45:12

Highway终极指南:解锁现代CPU向量计算的完整教程

Highway终极指南&#xff1a;解锁现代CPU向量计算的完整教程 【免费下载链接】highway 性能可移植的、长度无关的SIMD 项目地址: https://gitcode.com/GitHub_Trending/hi/highway 想要让代码性能飙升5-10倍&#xff1f;厌倦了为不同CPU架构编写多套SIMD代码&#xff1f…

作者头像 李华
网站建设 2026/3/21 1:00:07

5步搞定Monaco Editor多线程架构:从原理到实战的完整指南

当你第一次尝试集成Monaco Editor时&#xff0c;是否遇到过这样的场景&#xff1a;代码编辑器正常显示&#xff0c;但语法高亮失效、智能提示消失&#xff0c;控制台不断报出"Worker加载失败"的错误&#xff1f;这并非你的代码问题&#xff0c;而是Monaco Editor独特…

作者头像 李华