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

LeetCode 334:递增的三元子序列(贪心算法)—— 题解

👋 欢迎阅读

🎯 欢迎来到「递增的三元子序列」题解之旅!本文将带你从“判断数组中是否存在三个递增元素”这一搜索问题出发,深入理解贪心算法的精巧应用,并掌握如何仅用两个变量在 O(n)O(n) 时间内完成判断。

在开始之前,建议你先:

  • 了解题目背景:这是 LeetCode 334 题,给定整数数组nums,判断是否存在i<j<ki<j<k使得nums[i]<nums[j]<nums[k]nums[i]<nums[j]<nums[k]。这是LIS(最长递增子序列)的简化版,只需判断是否存在长度为 3 的递增子序列,无需求出完整 LIS。

  • 明确学习目标:掌握贪心 + 双变量追踪法(维护当前最小的两个递增元素firstsecond),理解为什么只需不断更新这两个变量即可判断三元组存在性。

  • 准备好环境:建议在本地 IDE 或 LeetCode 在线编辑器中打开代码,边看边运行,亲手验证示例(如nums = [2,1,5,0,4,6]输出true)。

本文将从问题转化、贪心策略设计、双变量模拟过程到代码实现,层层递进。即使你对贪心算法还不熟悉,我们也会从“维护当前最小的第一个数和第二个数”这一直觉出发,让你轻松抓住核心思想——只要不断更新最小前缀,就能判断是否有更大的数在后面形成三元组。现在,让我们一起在数组中寻找三个递增的“哨兵”,解开递增三元子序列的贪心密码吧! 🔍📊


一、题目

334. 递增的三元子序列 - 力扣(LeetCode)

二、做题思路

1. 问题分析(前置分析)

本题要求判断数组中是否存在长度至少为 3 的严格递增子序列。由于只关心是否存在,不需要找到具体序列,因此可以用贪心思想,维护当前最小的两个候选值,一旦遇到第三个比这两个都大的数,即说明存在递增三元组。


2. 贪心策略(核心决策规则)

  • 使用两个变量:

    • first表示当前找到的最小候选值(即尽可能小的第一个元素)。

    • second表示当前找到的大于first的最小候选值(即尽可能小的第二个元素)。

  • 遍历数组,按如下规则更新:

    • x <= first,则更新first = x(让第一个元素更小)。

    • 否则,若x <= second,则更新second = x(让第二个元素更小)。

    • 否则,说明找到了一个比firstsecond都大的数,返回true


3. 正确性说明(简单版本)

firstsecond分别存储了当前所有递增二元组中的最小和次小值。每次遇到一个新数时,若它比second还大,则说明它能与之前的一对(first, second)组成递增三元组,直接返回true。若xfirstsecond小,则更新对应值,为后续找到更小且更优的组合打基础。


4. 实现细节(边界防护)

  • 初始化first = nums[0]second = INT_MAX(表示尚未找到有效的第二小值)。

  • 遍历从第一个元素开始,依次按照上述规则更新。

  • 若遍历结束未返回true,则不存在递增三元组,返回false


5. 返回值(目标映射)

若在遍历过程中满足条件,直接返回true;否则遍历结束返回false

三、代码

class Solution { public: bool increasingTriplet(vector<int>& nums) { // 贪心策略:维护当前遇到的最小值 a 和次小值 b, // 一旦遇到大于 b 的数,说明找到了长度为3的递增子序列。 // 初始化: // a 为第一个元素,b 为 INT_MAX(表示还未找到次小值) int a = nums[0]; int b = INT_MAX; // 遍历数组,从第一个元素开始(也可从第二个开始,但当前代码从第一个开始) for (auto x : nums) { // 如果当前元素大于 a,说明它可以作为第二个或第三个元素 if (x > a) { // 如果当前元素还大于 b,则说明已经找到 a < b < x 的三元组 if (x > b) { return true; } else { // 否则,当前元素介于 a 和 b 之间,更新 b 为更小的次小值 b = x; } } else { // 当前元素不大于 a(即 <= a),更新 a 为更小的最小值 a = x; } } // 遍历结束仍未找到,返回 false return false; } };

四、流程图

🎯 闭幕

🎉 恭喜你完成了「递增的三元子序列」问题的学习!

为了巩固知识并进一步拓展,建议你:

🚀动手实践
在 LeetCode 上提交代码,尝试不同的测试用例。

💡深入思考

  • 本题要求是否存在长度为 3 的递增子序列,代码使用贪心维护两个变量ab,其中a是当前最小的“第一元素”,b是当前最小的“第二元素”。为什么这样维护就能判断是否存在三元组?你能用[2,1,5,0,4,6]手动模拟一下变量的变化过程吗?

  • 当遍历到某个数x时,如果x > a,我们尝试更新b;如果x > b则直接返回true为什么不直接记录第三个数,而要用ab两个变量?如果只用一个最小值min,能判断出三元组吗?

  • 代码中a初始化为nums[0]b初始化为INT_MAX。如果数组长度小于 3,循环结束后返回false,但题目保证长度至少为 1。如果nums全相等(如[1,1,1]),ab如何变化?最终返回什么?

  • 如果数组元素范围很大(正负均有),代码中的比较符号>是否仍然适用?如果要求严格递增,使用>正确;如果改为非递减,只需改成>=,你能快速调整吗?

📚延伸挑战

  • 将题目改为判断是否存在长度为 k 的递增子序列(k 为任意正整数),贪心法还能直接扩展吗?你会如何维护一个数组来记录每个长度的最小末尾值?(提示:参考“最长递增子序列”的贪心+二分)

  • 尝试将代码改为判断是否存在递减的三元子序列,只需要修改哪些比较符号?动手改一改。

如果你觉得本文对你有所帮助,欢迎:

👍 点赞 / 收藏
👤 关注作者,获取更多题解
💬 留言交流你的疑问或优化思路

祝你在算法之路上越走越稳,早日攻克每一道难题!下次见 🚀✨

http://www.cnnetsun.cn/news/3672012.html

相关文章:

  • 深岩银河存档编辑器:3步实现游戏资源自由的高效方案
  • 自一致性提示:多次采样提升推理准确率
  • Cursor Router智能模型路由:AI编程助手的自动调度核心技术解析
  • 手把手教你:CDN + 自建源站 HTTPS 证书部署全流程
  • FAB新人工程师成长指南:3年离职率降低一半的结构化培养方案
  • SSA优化ELMAN神经网络的光伏功率预测方法
  • JMeter性能测试实战:如何精准配置业务请求比例模拟真实流量?
  • 从零到一:raylib游戏开发终极入门指南 - 5分钟创建你的第一个游戏窗口
  • yuzu模拟器:在PC上畅玩Switch游戏的终极完整指南
  • 大模型应用实战:从入门到落地的关键技术解析
  • 3步搞定Windows 10老旧串口设备通信难题:PL-2303驱动修复全攻略
  • 后端系统的容量规划实践:跨行业的通用方法论与工具链
  • C# WinForms坦克大战实战:从零构建经典游戏,掌握游戏开发核心原理
  • Safari MCP服务器:AI驱动的Web自动化调试与测试实践
  • RCE漏洞绕过实战:从黑名单过滤到无回显利用的攻防解析
  • Unity跨平台开发中系统字体问题的深度解析与解决方案
  • mv移动文件、重命名文件实战案例
  • AI驱动的技能评估系统:动态校准个人技术栈
  • AI修图实战:把健身照片做成Q版分身手账涂鸦风
  • Unity游戏开发入门:从零实现小球吃金币的完整项目实战
  • 埋头代码,开口成长
  • UE5对话系统开发指南:从数据驱动到高级集成的完整实现方案
  • 【Python毕业设计】基于 Python 的智能化车辆故障记录与排查辅助系统 车队车辆故障运维管理信息系统实现(源码+文档+远程调试,全bao定制等)
  • Preference Orchestrator: Prompt-Aware Multi-Objective Alignment for Large Language Models
  • 基于DirectX Raytracing的实时光线追踪实践:从DXR API到渲染管线搭建
  • AlphaFold如何革新蛋白质结构预测与生物研究
  • AI论文降重与AIGC检测规避双降方案
  • Gemini生成的表格怎么复制下来?AI导出鸭横评四方案破局
  • 冰球数据分析:机器学习模型架构与实战应用
  • 数据集划分与交叉验证方法|留出法+K折+分层K折+时序划分对比