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

7.力扣【三数之和】史上最清晰双指针解法!三步搞定,面试必看!

目录

1. 题目解析

1.1 题目描述

15. 三数之和​

示例 1:

手写图示解析:

2. 算法原理

2.1 解法一:排序 + 暴力枚举 + 利用 set 去重 —— O(n³)

2.2 解法二:排序 + 双指针 —— O(n²)

步骤:

手写图示:

处理细节问题:

1. 去重:

2. 不漏:

优化点:

3. 编写代码

总结


OJ链接:https://leetcode.cn/problems/3sum/description/


1. 题目解析

1.1 题目描述

15. 三数之和

难度:中等

给你一个整数数组nums,判断是否存在三元组[nums[i], nums[j], nums[k]]满足i != ji != kj != k,同时还满足nums[i] + nums[j] + nums[k] == 0。请你返回所有和为 0 且不重复的三元组。

注意:答案中不可以包含重复的三元组。

示例 1:

输入:nums = [-1,0,1,2,-1,-4]

输出:[[-1,-1,2],[-1,0,1]]

解释:

  • nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0

  • nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0

  • nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0

    不同的三元组是[-1,0,1][-1,-1,2]

    注意:输出的顺序和三元组的顺序并不重要。

手写图示解析:

原数组:[-1, 0, 1, 2, -1, -4]

→ 排序后:[-4, -1, -1, 0, 1, 2]

→ 尝试组合:

  • [-1, 0, 1]✔️

  • [-1, 2, -1]✔️

  • [0, 1, -1]×

注:对三元组[−1, 0, 1][−1, 2, −1]的判断,以及[0, 1, −1]被划掉,说明答案中不可包含重复的三元组,即使数值相同,顺序不同也视为重复。


2. 算法原理

2.1 解法一:排序 + 暴力枚举 + 利用 set 去重 —— O(n³)

思路:

先对数组排序,然后用三重循环枚举所有可能的三元组,将符合条件的存入Set中去重,最后转为列表返回。

手写图示:

排序后数组:[-4, -1, -1, 0, 1, 2]

→ 找到[-1, 0, 1]两次,说明需要去重。

→ 箭头指向O(n³)表示时间复杂度。

缺点:​ 时间复杂度高,效率低下。


2.2 解法二:排序 + 双指针 —— O(n²)

步骤:

  1. 排序:将数组升序排列。

  2. 固定一个数a(即nums[i])。

  3. 在该数后面的区间内,利用“双指针算法”快速找到两个数的和等于-a即可。

手写图示:

排序后数组:[-4, -4, -1, 0, 0, 0, 1, 1, 4, 4, 5, 6]

→ 固定i=0(值为-4),left=1right=11,目标值t=4

→ 指针移动过程图示清晰。

处理细节问题:

1. 去重:

  • 找到一种结果之后leftright指针要跳过重复元素:

    while(left < right && nums[left] == nums[left - 1]) left++; while(left < right && nums[right] == nums[right + 1]) right--;
  • 当使用完一次双指针算法之后i也需要跳过重复元素:

    while(i < n && nums[i] == nums[i - 1]) i++;

2. 不漏:

  • 找到一种结果之后,不要“停”,缩小区间,继续寻找。

优化点:
  • 固定数a <= 0:因为数组已排序,若a > 0,则后续所有数都大于0,三数之和不可能为0,可直接break

  • 避免越界:指针移动时需保证left < right


3. 编写代码

class Solution { // 时间复杂度 O(N^2) public List<List<Integer>> threeSum(int[] nums) { List<List<Integer>> ret = new ArrayList<>(); // 1. 排序 Arrays.sort(nums); // 2. 利用双指针解决问题 int n = nums.length; for(int i = 0; i < n; ) { if(nums[i] > 0) break; // 小优化 int left = i + 1, right = n - 1, target = -nums[i]; while(left < right) { int sum = nums[left] + nums[right]; if(sum > target) right--; else if(sum < target) left++; else { // nums[i] nums[left] nums[right] ret.add(new ArrayList<Integer>(Arrays.asList(nums[i], nums[left], nums[right]))); left++; right--; // 缩小区间继续寻找 // 去重: left right while(left < right && nums[left] == nums[left - 1]) left++; while(left < right && nums[right] == nums[right + 1]) right--; } } // 去重: i i++; while(i < n && nums[i] == nums[i - 1]) i++; } return ret; } }

总结

  • 核心思想:排序 + 双指针,将 O(n³) 优化至 O(n²)。

  • 关键点

    • 排序是基础。

    • 固定一个数,双指针找另外两个数。

    • 去重处理:三个地方(i,left,right)都要跳过重复元素。

    • 小优化:nums[i] > 0时直接 break,避免无效计算。

  • 易错点:去重逻辑必须严格,否则会包含重复三元组。

http://www.jsqmd.com/news/887053/

相关文章:

  • 单片机485实验
  • 汕头老药桔选购技术指南:潮汕特产老香黄、潮汕特产肉脯、潮汕特产茶叶、潮汕茶叶伴手礼、潮汕鸭屎香、正宗凤凰单枞、正宗鸭屎香选择指南 - 优质品牌商家
  • MBTI性格测试
  • ARM PMU性能监控单元原理与实践指南
  • Linux系统启动慢?从UEFI的DXE阶段入手,优化驱动加载让你的开机快人一步
  • 户外实用|艾迪欧 R6000 测评 —— 户外 / 自驾 / 露营的通讯好搭档
  • Python合并Excel文档
  • 2026上半年数据库系统工程师(软考)上午题回忆与解析(非标答版)
  • 2026年山东大学软件学院创新项目实训博客(六)
  • 终极鼠标连点器使用指南:3分钟掌握高效自动化技巧
  • %u的几个格式化输出版本
  • 潮州东方轻奢风全屋高定找哪家
  • 贵阳婚礼西服定制攻略:面料、工艺、版型避坑指南
  • 量子软件测试的挑战与优化策略
  • DeepSeek-R1推理延迟骤降41.8%?独家披露3类硬件感知调度策略(A100/H100/MI300X实测对比数据)
  • 谁懂啊!Win11 部署 OpenClaw 踩过的坑,2.7.5 版本一次性解决
  • Simulink中Repeating Sequence锯齿波显示恒为0解决方案
  • 别再用SonarQube凑数了!DeepSeek原生圈复杂度引擎的6大颠覆性能力(含GitHub私有部署密钥)
  • DDD在DeepSeek场景中失效的7种典型征兆,第5种正在 silently 毁掉你的推理一致性
  • 终极指南:如何用ComfyUI-Manager轻松管理你的AI工作流扩展库
  • Veo 2胶片质感生成器失效?——深度解析Color Science v2.3内核中被屏蔽的Cinematic Grain Injection层
  • 从Sora 2原始张量到可交付MP4:端到端Pipeline中被92%开发者忽略的色彩空间转换断点(BT.2020→BT.709→sRGB三级校准手册)
  • 竞赛题解题方法
  • 基于DINOv2实现特征匹配异常检测
  • PIML技术提升CFD湍流模拟精度:从数据驱动到工程应用实践
  • 沪电股份一季度AI营收62亿元:从英伟达GPU打样到1.6T交换机配套
  • DeepSeek开源协议识别深度解析(MIT/Apache/GPL三协议法律边界大揭秘)
  • 从Dark Channel Prior到AOD-Net:手把手带你复现5个经典图像去雾算法(Python/PyTorch)
  • 【限时解密】Sora 2内部GIF编码协议曝光:如何用Python脚本强制启用LZW+Alpha通道(含GitHub私藏工具包)
  • Midjourney云雾动态演化技巧(雾流速/雾密度/雾边界锐度三维调控法):内含仅限订阅用户获取的雾效时间轴Prompt模板库