news 2026/4/23 11:35:39

day163—递归—买卖股票的最佳时机含冷冻期(LeetCode-309)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
day163—递归—买卖股票的最佳时机含冷冻期(LeetCode-309)

题目描述

给定一个整数数组prices,其中第prices[i]表示第i天的股票价格 。​

设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票):

  • 卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。

注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

示例 1:

输入:prices = [1,2,3,0,2]输出:3解释:对应的交易状态为: [买入, 卖出, 冷冻期, 买入, 卖出]

示例 2:

输入:prices = [1]输出:0

提示:

  • 1 <= prices.length <= 5000
  • 0 <= prices[i] <= 1000

解决方案:

这段代码是基于记忆化递归求解 “含冷冻期的股票买卖最佳时机” 问题(买入股票后需隔至少一天才能再次操作,即卖出后次日不能买入),在原有无限次交易递归逻辑的基础上,仅修改了 “买入” 操作的前驱状态,适配了冷冻期规则,同时保留记忆化优化以解决超时 / 栈溢出问题。

核心逻辑

  1. 核心定义

    • memo:二维记忆化数组(len×2),memo[end][0/1]缓存dfs(end, is)的结果(0 = 不持有股票,1 = 持有股票),避免重复递归;
    • dfs(end, is, nums):返回从第 0 到第end天,在is状态(true= 持有、false= 不持有)下能获得的最大利润,且满足 “冷冻期” 规则。
  2. 递归边界

    • end < 0(所有天数遍历完毕):
      • is=true(仍持有股票),返回-0xFFFF(极小值,代表非法状态);
      • is=false(不持有股票),返回 0(无交易时利润为 0)。
  3. 记忆化优化:计算dfs(end, is)前,先检查memo[end][state]state为 0/1 对应不持有 / 持有),若不为 - 1 则直接返回缓存值,避免重复递归,时间复杂度从O(2n)降至O(n)。

  4. 状态转移(核心:适配冷冻期)

    • 持有股票(is=true):代表第end天买入了股票,因冷冻期规则,买入前必须保证第end-1天不操作(即前驱状态为end-2天不持有),因此利润取:
      • 继续持有:dfs(end-1, true, nums)(第end天不操作,保持持有);
      • 买入股票:dfs(end-2, false, nums) - nums[end](第end天买入,成本为nums[end],且前驱是end-2天不持有,规避冷冻期);
      • 最终取两者最大值。
    • 不持有股票(is=false):代表第end天卖出或不操作,无冷冻期限制,利润取:
      • 继续不持有:dfs(end-1, false, nums)(第end天不操作);
      • 卖出股票:dfs(end-1, true, nums) + nums[end](第end天卖出,收益为nums[end]);
      • 最终取两者最大值。
  5. 主函数逻辑:初始化记忆化数组,调用dfs(len-1, false, prices)(从最后一天、不持有股票的初始状态开始计算),返回符合冷冻期规则的最大利润。

关键特点

  • 规则适配:仅修改 “买入” 操作的前驱状态为end-2,精准适配 “卖出后次日不能买入” 的冷冻期规则;
  • 效率优化:记忆化缓存解决了纯递归的超时 / 栈溢出问题,能处理大数据量用例;
  • 逻辑兼容:保留原有递归框架,仅最小化修改核心状态转移,易理解、易维护。

总结

  1. 核心思路:在记忆化递归的基础上,通过调整 “买入” 操作的前驱状态(从end-1改为end-2),适配股票买卖的冷冻期规则;
  2. 关键设计:memo数组缓存状态结果是效率核心,end-2的前驱状态是冷冻期规则的核心体现;
  3. 功能效果:能正确计算含冷冻期的股票最大利润,稳定通过大数据量用例。

函数源码:

class Solution { public: vector<vector<int>> memo; // 仅修改该函数:增加记忆化+修正状态转移符号+规范边界值 int dfs(int end, bool is, vector<int>& nums) { int len = nums.size(); if(end < 0) { // 边界值修正:用INT_MIN表示持有股票的非法状态,更规范 if(is) return -0xFFFF; return 0; } int state = is ? 1 : 0; // 0=不持有,1=持有 if (memo[end][state] != -1) { return memo[end][state]; } int res; if(is) { res = max(dfs(end-1, true, nums), dfs(end-2, false, nums) - nums[end]); } else { res = max(dfs(end-1, false, nums), dfs(end-1, true, nums) + nums[end]); } // 缓存当前状态的结果 return memo[end][state] = res; } int maxProfit(vector<int>& prices) { int len = prices.size(); if (len == 0) return 0; // 空数组边界处理 // 初始化记忆化数组(len行2列,初始值-1表示未计算) memo.assign(len, vector<int>(2, -1)); // max(0, ...) 确保利润不会为负(无交易时利润为0) return dfs(len-1, false, prices); } };
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/23 11:35:03

ASP.NET Core面试精讲系列三

目录 31. ASP.NET Core 中的 MVC 是什么&#xff1f;与“老版”ASP.NET 的 MVC 有何不同&#xff1f; MVC 的定义 ASP.NET Core MVC 与 ASP.NET MVC 的主要区别 32. 什么是 Razor Pages&#xff1f;何时使用 Razor Pages 而不是 MVC&#xff1f; 推荐使用 Razor Pages 的场…

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

2026年还在靠“开机等单”跑网约车?学会这几条,超越同城80%的司机!

亲爱的司机师傅&#xff0c;如果你还在靠“开机等单”跑网约车&#xff0c;那今天的文章&#xff0c;请你一定看完。跑车早已不是拼体力、拼时间的年代。真正能站稳脚跟、赚得盆满钵满的&#xff0c;都是懂得借平台之力、摸透接单逻辑的“智慧型司机”。从现在起&#xff0c;改…

作者头像 李华
网站建设 2026/4/23 5:22:01

深入解析反广告拦截器的技术实现原理

在浏览网页时&#xff0c;浏览器与服务器之间进行着频繁的数据交换。用户希望快速获取内容&#xff0c;而发布者往往需要通过展示商业信息来维持运营。当浏览器扩展程序介入并试图隐藏这些商业信息时&#xff0c;网页端的脚本便会启动一种检测机制。这种反广告拦截技术并非不可…

作者头像 李华
网站建设 2026/4/21 7:36:49

导师严选2026 AI论文平台TOP8:MBA开题报告全测评

导师严选2026 AI论文平台TOP8&#xff1a;MBA开题报告全测评 2026年MBA论文写作工具测评&#xff1a;为何需要一份权威榜单&#xff1f; MBA学生在撰写开题报告与论文过程中&#xff0c;常面临选题思路不清晰、文献资料查找困难、格式规范不熟悉等挑战。随着AI技术的不断进步&a…

作者头像 李华
网站建设 2026/4/9 12:28:32

嵌入式 C 语言进阶:内存管理与指针优化的实战技巧

第一部分&#xff1a;嵌入式系统内存架构的深度解析嵌入式内存层次结构与访问特性嵌入式系统的内存架构呈现出明显的层次化特征&#xff0c;每个层次都具有独特的访问速度、容量和功耗特性。最接近处理器核心的是寄存器文件&#xff0c;提供纳秒级的访问速度但数量极为有限&…

作者头像 李华