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

LeetCode 15:三数之和 | 双指针法详解与进阶应用

LeetCode 15三数之和 | 双指针法详解与进阶应用引言三数之和3Sum是 LeetCode 中一道经典的高频面试题编号为 15属于 Medium 难度范畴。这道题的核心要求是在一个整数数组中找出所有不重复的三元组使得这三个数之和为零。由于其看似简单但实现细节丰富的特点三数之和成为了考察算法思维和代码实现能力的重要题目。三数之和的暴力解法时间复杂度为 O(n³)对于大规模数据显然无法接受。更优的解决方案采用双指针技巧将时间复杂度降低到 O(n²)同时通过巧妙的去重机制避免重复三元组的产生。本文将深入剖析双指针法解决三数之和的原理、实现细节以及各种边界情况的处理帮助读者彻底掌握这一经典问题的解题思路。问题分析题目描述给定一个整数数组 nums判断是否存在元素 a、b、c 使得 nums[i] nums[j] nums[k] 0i ≠ j、i ≠ k 且 j ≠ k并返回所有满足条件的不重复三元组。例如对于输入 [-1, 0, 1, 2, -1, -4]满足条件的三元组有 [[-1, -1, 2], [-1, 0, 1]]。问题特点三数之和问题具有以下几个显著特点使其成为算法学习中的经典案例。首先由于需要返回所有满足条件的三元组而不是仅仅判断是否存在因此需要穷举所有可能的组合。其次要求返回的三元组不能重复这意味着需要对结果进行去重处理。最后为了在 O(n²) 时间复杂度内解决此问题必须采用高效的搜索策略双指针法正是为此量身定做的技巧。从更宏观的角度看三数之和实际上是更广泛的 K 数之和问题的一个特例。当 K 大于 2 时可以通过递归的方式将 K 数之和问题转化为若干个 (K-1) 数之和问题但这种递归方法的时间复杂度会随着 K 的增大而指数增长。对于三数之和这一特殊情形双指针法提供了更为优雅和高效的解决方案。暴力解法分析考虑最直接的暴力解法我们可以使用三层嵌套循环遍历所有可能的三元组检查其和是否为零。这种方法的时间复杂度为 O(n³)空间复杂度为 O(1)。假设 n 为 1000那么需要执行约 10 亿次运算这对于现代计算机来说仍然是一个相当耗时的操作。更重要的是暴力解法会产生大量重复的三元组后续去重过程同样需要额外的时间和空间开销。双指针法原理排序预处理双指针法解决三数之和的第一步是对数组进行排序。排序的目的有两个一是通过将相等的元素聚集在一起方便后续的去重操作二是为双指针的移动提供方向性指导。排序后数组呈现非递减的顺序这意味着当指针指向某个元素时我们可以根据该元素与目标值的关系来决定指针的移动方向。排序操作的时间复杂度为 O(n log n)这是双指针法总时间复杂度 O(n²) 中不可忽视的一部分。虽然排序增加了时间成本但它为整个算法提供了重要的有序性保证使得后续的搜索过程可以更加高效地进行。需要注意的是排序会改变原有数组元素的相对位置但由于我们只需要返回满足条件的三元组而不需要知道这些三元组中元素的原始索引因此这种改变是无害的。固定一个数在排序后的数组中我们首先固定一个元素作为三元组中的第一个数。假设固定的是 nums[i]那么问题就转化为在剩余的 nums[i1] 到 nums[n-1] 范围内找到两个数使它们的和等于 -nums[i]。这一步将原问题从三数之和转化为两数之和问题而两数之和正是双指针法最经典的应用场景。对于 nums[i] 的选择我们需要特别注意去重。当 nums[i] 与前一个元素 nums[i-1] 相同时如果继续以 nums[i] 为第一个数进行搜索会产生与之前搜索重复的三元组。因此当我们遇到连续相同的元素时应该直接跳过将 i 移动到下一个不同元素的位置。这种去重策略是双指针法高效性的重要保障。两侧指针搜索在确定了固定的第一个数 nums[i] 后我们在 [i1, n-1] 区间内设置两个指针left 指向区间的左端点 i1right 指向区间的右端点 n-1。此时我们的目标是找到 nums[left] nums[right] -nums[i] 的情况。如果三数之和大于零说明需要减小总和由于数组已排序减小 right 指针可以减小 nums[right] 的值如果三数之和小于零说明需要增大总和增大 left 指针可以增大 nums[left] 的值。这一搜索过程持续进行直到 left 和 right 指针相遇此时我们已经检查了所有可能的二元组合。每次找到满足条件的三元组后需要将 left 和 right 指针都向中间移动并跳过所有与当前元素相同的值以避免产生重复的三元组。这种移动策略确保了每个不同的三元组只会被发现一次。完整代码实现from typing import List class Solution: def threeSum(self, nums: List[int]) - List[List[int]]: n len(nums) if n 3: return [] nums.sort() result [] for i in range(n - 2): if nums[i] 0: break if i 0 and nums[i] nums[i - 1]: continue left, right i 1, n - 1 target -nums[i] while left right: total nums[left] nums[right] if total target: result.append([nums[i], nums[left], nums[right]]) while left right and nums[left] nums[left 1]: left 1 while left right and nums[right] nums[right - 1]: right - 1 left 1 right - 1 elif total target: left 1 else: right - 1 return result上述实现中包含了几个关键的去重技巧。首先在外层循环中跳过与前一个元素相同的 nums[i]避免以相同的数字作为三元组的第一个元素。其次在找到一个满足条件的三元组后通过 while 循环跳过所有与 nums[left] 和 nums[right] 相同的元素避免产生重复的三元组。这些去重操作确保了最终返回的结果集中不包含任何重复的三元组。算法复杂度分析时间复杂度双指针法解决三数之和问题的时间复杂度为 O(n²)。这是因为外层循环最多遍历 n-2 次而每次内层的双指针搜索过程在最坏情况下也会移动 O(n) 次。具体来说外层循环的时间复杂度为 O(n)内层双指针搜索的时间复杂度同样为 O(n)两者相乘得到总时间复杂度 O(n²)。排序操作的时间复杂度 O(n log n) 在大 O 表示法中被更高级的 O(n²) 吸收因此最终的时间复杂度仍为 O(n²)。空间复杂度算法的空间复杂度为 O(1)不包括输出结果所占用的空间。这是因为双指针法只需要使用常数个额外变量来存储指针位置、中间计算结果等而不需要使用额外的数据结构来存储数组元素。返回的结果列表虽然占用了空间但在计算空间复杂度时通常不计入输出参数所占用的空间。边界情况处理空数组和短数组当输入数组的长度小于 3 时无论如何都无法组成三元组因此直接返回空列表。这是代码中最基本但也最容易忽略的边界检查。类似地当数组中所有元素都大于零时由于三个正数之和永远不可能为零可以提前终止外层循环这种优化在实际应用中可以显著减少不必要的计算。包含重复元素的数组去重是三数之和问题的核心难点之一。考虑输入 [-1, -1, -1, 2, 2, 2]如果不去重可能会产生多个相同的三元组 [-1, -1, 2]。去重策略的核心是当我们在遍历过程中遇到与前一个元素相同的值时直接跳过。这种策略基于一个重要的观察如果以相同的值作为三元组的第一个或第二个、第三个元素那么之前已经搜索过所有以该值开头的情况再次搜索只会产生重复结果。包含零的特殊情况零在这个问题中具有特殊意义因为 -nums[i] 本身可能为零。考虑输入 [-1, 0, 1, 2, -1, -4]其中存在 nums[j] 0 的情况。当 nums[i] nums[j] nums[right] 0 时意味着找到了一个包含零的三元组。由于零既不是正数也不是负数它不会影响排序后数组的单调性因此双指针的移动策略在包含零的情况下仍然有效。代码中对 nums[i] 0 的提前终止条件需要特别注意因为当 nums[i] 0 时即使后面的元素之和也为负三数之和仍可能为零。变种问题四数之和LeetCode 18四数之和是三数之和的直接扩展要求在数组中找到四个数之和等于目标值。最直观的解法是固定两个数然后使用双指针在剩余范围内寻找两个数使四数之和等于目标值。这种方法的时间复杂度为 O(n³)空间复杂度为 O(1)。另一种思路是使用哈希表将四数之和转化为两数之和问题但空间复杂度会增加。对于四数之和去重逻辑会更加复杂需要同时对四个位置进行去重处理。最接近的三数之和LeetCode 16最接近的三数之和问题要求找到三个数使它们的和最接近目标值。与原问题不同这里不需要精确等于目标值而是要找最接近的组合。解决这个问题可以在三数之和的基础上稍作修改在遍历过程中计算当前三数之和与目标值的差的绝对值如果这个值比之前记录的最小差值更小则更新结果。由于不需要精确相等双指针的移动策略保持不变但不需要进行去重操作。统计三数之和为特定值的情况数如果问题不是返回具体的三元组而是统计三数之和等于目标值的情况数那么可以去重优化专注于计数。这种变种问题在某些实际应用场景中更常见例如在统计分析中计算某种组合的总数。解决思路与标准三数之和类似但在找到满足条件的三元组后不是添加到结果集中而是增加计数器的值。实际应用场景三数之和问题看似是一个纯学术性的算法问题但它在许多实际应用场景中都有重要的应用价值。在数据分析领域三数之和可以用于查找满足特定条件的组合例如在金融数据分析中寻找收益为零的投资组合。在游戏开发中三数之和的变种可以用于计算游戏中的得分组合或技能搭配。在图像处理和计算机视觉中三数之和的思想也被用于特征匹配和三维重建等场景。此外双指针作为一种通用的问题解决技巧其应用范围远不止三数之和问题。在处理有序数组的两数之和、两数之积、滑动窗口等问题时双指针法都展现出了极高的效率。因此深入理解三数之和问题的解决思路对于提升整体算法能力具有重要意义。总结三数之和问题是一道经典的算法面试题它巧妙地将双指针技巧与去重策略结合在一起以 O(n²) 的时间复杂度解决了看似简单却细节丰富的问题。通过对这道题的学习我们不仅掌握了双指针法的核心原理还深入理解了处理重复元素的技巧。在实际面试中三数之和及其变种问题经常出现能够清晰准确地实现这道题的候选人往往能给面试官留下良好的印象。通过本文的详细讲解希望读者能够彻底掌握三数之和问题的解决方法并将其中的算法思想融会贯通应用于更多类似问题的解决中。双指针法作为一种强大的算法技巧值得我们在实践中不断加深理解和应用。

相关文章:

LeetCode 15:三数之和 | 双指针法详解与进阶应用

LeetCode 15:三数之和 | 双指针法详解与进阶应用 引言 三数之和(3Sum)是 LeetCode 中一道经典的高频面试题,编号为 15,属于 Medium 难度范畴。这道题的核心要求是在一个整数数组中找出所有不重复的三元组,使…...

为什么你的双色调总像PPT?揭秘Midjourney v6中未公开的--tint权重衰减算法与Gamma校准阈值

更多请点击: https://kaifayun.com 第一章:双色调视觉失真的本质归因 双色调视觉失真并非单纯由显示设备或图像压缩引发的表层现象,其根本源于人眼视锥细胞响应函数与数字色彩空间映射之间的结构性不匹配。当图像被强制量化为仅含两种色调&a…...

什么是虚拟化

什么是虚拟化? 什么是虚拟化 虚拟化长期以来一直是一项基础 IT 技术,使企业能够在一台物理机器上运行多个独立的系统。 虚拟化是一种允许从单个物理机创建多个虚拟环境的技术。这些虚拟环境基本上是以前与硬件绑定的功能的逻辑(虚拟&#xff…...

【bash】git-bash windows 配置ssh免密登录ubuntu

需要一台ubuntu机器,长期运行 作为代理服务器,帮我访问github等白名单网络。 期望端口映射,长期运行。 在 Git Bash 环境下 在 Git Bash 环境下!Git Bash 确实完美支持 ~ 符号,而且我看到你的 ~/.ssh/ 目录下,id_ed25519.pub 已经静静地躺在那里了。 既然文件都在,而且…...

卡梅德生物技术快报|噬菌体随机肽库筛选实战:花生过敏原 Ara h 5 模拟表位鉴定全流程

摘要本文面向生物研发、体外诊断、蛋白质工程开发者,系统讲解噬菌体随机肽库筛选过敏原模拟表位完整工程化流程:从问题分析、实验设计、关键参数到结果验证,提供可复现技术方案,基于真实研究数据,聚焦高可靠性表位筛选…...

从 0 到 1:10 分钟跑通第一个 Ascend ACL 推理程序

第一次在昇腾 NPU 上跑推理,很多人卡在第一步:环境装好了,ATC 模型转换也成功了,一跑推理程序就报 aclInit failed 或者 load model failed。 我当年第一次跑 ACL 推理,环境装了 3 遍,模型转了 5 遍&#…...

2026 软考中级《多媒体应用设计师》备考全攻略(附全套资料)

大家好,最近很多朋友问我软考多媒体应用设计师的备考方法和资料整理问题,今天就把我自己整理的备考资料和实用经验一次性分享给大家,帮你少走弯路,高效备考~ 📚 我的备考资料整理(4 大模块全覆…...

WT32-S3-DK开发板全解析:从硬件设计到物联网项目实战

1. 项目概述:一块“小而全”的物联网开发板最近在捣鼓一个智能家居的传感器节点项目,需要一块性能足够、接口丰富、最好还带屏幕的开发板。市面上ESP32-S3的方案很多,但要么是核心板,需要自己配底板和屏幕,要么就是功能…...

基于ZYNQ与IgH的EtherCAT主站方案:软硬协同实现工业实时控制

1. 项目概述:当工业实时网络遇上可编程SoC在工业自动化领域,实时性和确定性是永恒的核心诉求。EtherCAT作为高性能的工业以太网协议,以其独特的“飞读飞写”数据处理机制和极低的通信抖动,成为了众多高精度运动控制、机器人、半导…...

ZYNQ平台开源EtherCAT主站部署与实时运动控制优化实践

1. 项目概述与核心价值最近在做一个基于ZYNQ的工业运动控制项目,客户对多轴同步的实时性和抖动要求非常高,传统的脉冲或总线方案在复杂轨迹规划下显得有些力不从心。经过一番调研和选型,最终决定上马EtherCAT总线。作为工业以太网领域的“性能…...

Linux内核调试利器:/proc/sysrq-trigger原理与实战指南

1. 内核调试的“后门”:/proc/sysrq-trigger 深度解析在Linux内核开发和系统调试的深水区,当系统完全无响应、键盘鼠标失灵,甚至SSH连接都彻底中断时,常规的调试手段往往束手无策。这时,一个隐藏在/proc文件系统中的特…...

AI Agent Harness Engineering 在餐饮行业的应用:智能点餐与库存管理

标题选项 《从排队到零浪费:AI Agent Harness Engineering 重构餐饮智能点餐与库存管理全链路》 《AI Agent 落地餐饮行业实战:基于Harness框架打造高可用智能点餐+库存联动系统》 《告别漏单、超卖、食材浪费:AI Agent Harness 工程化在餐饮场景的落地指南》 《垂直行业Age…...

AI Agent Harness Engineering 技术选型指南:根据场景选择合适的大模型与框架

AI Agent Harness Engineering 技术选型指南:根据场景选择合适的大模型与框架 引言 痛点引入 你是否遇到过这样的场景?产品经理拍板要做一个**“能帮企业HR自动筛选简历、邀约面试、生成入职指南并跟进试用期转正材料”**的“超级HR助手”AI Agent——…...

自动化文件管理:基于Python的网盘批量处理方案

自动化文件管理:基于Python的网盘批量处理方案 【免费下载链接】BaiduPanFilesTransfers 百度网盘批量转存、分享和检测工具 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduPanFilesTransfers 在数字资源日益丰富的时代,百度网盘用户面临着批…...

38 - Go 命令行参数处理:从 os.Args 到 flag 的底层设计

文章目录38 - Go 命令行参数处理:从 os.Args 到 flag 的底层设计为什么需要命令行参数?命令行参数的本质最基础的参数处理:os.Args基础使用示例获取单个参数flag 标准库:Go 官方参数解析器最简单的 flag 示例为什么 flag.String 返…...

RK3588 Android系统签名实战:为APK获取系统权限完整指南

1. 项目概述与核心价值在嵌入式Android开发领域,尤其是基于瑞芯微(Rockchip)平台如RK3588进行产品研发时,我们常常会遇到一个核心需求:如何让一个普通的第三方APK应用,获得系统级(System&#x…...

2025亲测好用的论文降AI工具,降重稳还不打乱原格式

说真的,现在写论文最慌的已经不是重复率飘红,而是AI检测率超标。尤其是用过AI辅助写作或者改写的同学,检测报告一出来AI率直奔80%,导师一句“这是你自己写的?”就能让人瞬间心脏骤停。 我最近花了一周时间,…...

全志T113-i平台UB37三模无线模组驱动移植与调试实战

1. 项目概述:当国产工业芯遇上新一代无线技术最近在做一个挺有意思的项目,客户想在一块国产的工业级核心板上,集成最新的星闪(NearLink)无线通信功能。核心板用的是全志的T113-i,无线模组是支持Wi-Fi 6、蓝…...

全志T113-S3开发板网络配置实战:从DHCP到静态IP与故障排查

1. 项目概述:从零上手T113-S3的网络配置刚拿到一块新的全志T113-S3开发板,比如眺望电子的EVM-T113-S3,第一件事你会做什么?我的习惯是,先把它“连上网”。这听起来简单,但却是后续所有高级操作——无论是通…...

RK3588开发板接口测试实战:USB、CAN、UART、GPIO全解析

1. 项目概述与核心价值作为一名在嵌入式开发领域摸爬滚打了十多年的老工程师,我深知拿到一块新开发板后,那种既兴奋又有点无从下手的感觉。特别是像RK3588这样功能强大的核心板,接口丰富,性能强劲,但如何快速验证这些基…...

3个理由告诉你:为什么Notepad2-mod是你开启开源贡献的最佳起点

3个理由告诉你:为什么Notepad2-mod是你开启开源贡献的最佳起点 【免费下载链接】notepad2-mod LOOKING FOR DEVELOPERS - Notepad2-mod, a Notepad2 fork, a fast and light-weight Notepad-like text editor with syntax highlighting 项目地址: https://gitcode…...

VM振弦采集模块精度实测:从标准信号源到误差分析全流程

1. 项目概述与核心价值最近在做一个岩土工程安全监测的项目,其中有个环节让我琢磨了好一阵子:如何准确地评估我们用的那批VM振弦采集模块的测量精度。这玩意儿在结构健康监测、桥梁隧道、边坡稳定性监测里用得非常多,核心任务就是读取振弦式传…...

Midjourney中画幅风格不生效?5个致命配置错误正在 silently 毁掉你的成片率

更多请点击: https://kaifayun.com 第一章:Midjourney中画幅风格失效的真相与底层机制 Midjourney 中的中画幅(Medium Format)风格常被用户以 --style medium-format 或关键词 medium format film 调用,但大量实测表…...

振弦采集模块精度检测实战:从原理到环境测试全解析

1. 项目概述与核心目标在工程监测领域,振弦式传感器因其长期稳定性好、抗干扰能力强、信号传输距离远等优点,被广泛应用于桥梁、大坝、隧道、边坡等结构物的应力、应变、位移和压力监测。而VM系列振弦采集模块,作为连接传感器与数据采集系统的…...

提示词失效?Midjourney印象派出图不稳的8大陷阱,资深AIGC架构师逐帧解析SD/MJ风格迁移差异

更多请点击: https://codechina.net 第一章:提示词失效的本质:当语义熵击穿Midjourney的隐空间边界 当“cyberpunk cat wearing neon sunglasses, ultra-detailed, 8k”生成结果突然坍缩为 a blurry humanoid silhouette with cat ears&…...

消费电子贴膜的光学技术革新:圆偏振光与磁控溅射AR的原理解析

摘要随着用户对屏幕使用健康关注的提升,消费电子贴膜行业正在经历从“物理防护”到“光学级视觉守护”的技术升级。本文从光学原理出发,解析圆偏振光柔光标准与磁控溅射AR抗眩镀膜两项核心技术的工作机制,并分析其在屏幕保护场景中的应用逻辑…...

Linux ln 软硬链接详解——底层原理+生产实战+彻底区分(零踩坑)

前言很多新手永远分不清软硬链接,只会背“软链接像快捷方式、硬链接像副本”,一旦遇到生产删文件、日志切割、程序部署就翻车。本文从inode底层原理讲起,配合完整实战、对比、生产场景,让你彻底吃透 ln 软硬链接,面试、…...

AhMyth:跨平台Android远程管理工具的完整指南与实战教程

AhMyth:跨平台Android远程管理工具的完整指南与实战教程 【免费下载链接】AhMyth Cross-Platform Android Remote Administration Tool | The only maintained version of AhMyth on github | A revival of the original repository at https://GitHub.com/AhMyth/A…...

软考高项案例分析8:项目风险管理

软考高项案例分析8:项目风险管理 一、项目风险管理过程 1、规划风险管理; 2、识别风险; 3、实施定性风险分析; 4、实施定量风险分析; 5、规划风险应对; 6、实施风险应对; 7、监督风险; 二、案例分析知识点 1. 风险应对措施 威胁应对策略:上报、规避、转移、…...

透明化智慧港口码头•装载·存储·集散全流程透明化管控方案

一、方案前言本方案依托黎阳之光镜像孪生、时空AI拓扑、无感全域定位、视频实景融合、边缘实时算力五大核心技术,聚焦港口码头货物装载、堆场存储、集疏运集散三大核心业务,打造实景可视、数字镜像、智能调度、全程透明、风险可控、全程可溯的智慧管控体…...