Evan Wang
Evan WangFrontEnd Developer
  • Evan Wang
    Evan WangFrontEnd Developer
  • 前端相关
  • 算法题
  • 日常笔记
  • Chat With AI

两数之和
两数相加
无重复字符的最长子串
最长回文子串
盛水最多的容器
三数之和
电话号码的字母组合
有效括号
合并两个有序链表
括号生成
下一个排列
搜索旋转排序数组
在排序数组中查找元素的第一个和最后一个位置
删除链表的倒数第n个节点
组合总和
全排列
旋转图像
字母异位词分组
最大子数组合
跳跃游戏
反转链表
反转链表2
合并区间
最小路径和
编辑距离
颜色分类
爬楼梯
组合
子集
不同的二叉搜索树
验证二叉搜索树
对称二叉树
二叉树的层序遍历
二叉树的最大深度
从前序与中序遍历序列构造二叉树
只出现一次的数字
二叉树展开为链表
最长连续序列
单词拆分
环形链表
环形链表2
排序链表
相交链表
乘积最大子数组
最小栈
多数元素
打家劫舍
数组中重复的数据
二叉树的中序遍历
卖股票的最佳时机
数组中的第K个最大元素

  1. Articles
  1. More
  2. 6-三数之和.mdx
目录
题目思路代码
1511 字
约 4 分钟
更新于 2026/08/20

三数之和

题目:

给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且j != 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] 。
注意,输出的顺序和三元组的顺序并不重要。

示例 2:

输入:nums = [0,1,1]
输出:[]
解释:唯一可能的三元组和不为 0 。

示例 3:

输入:nums = [0,0,0]
输出:[[0,0,0]]
解释:唯一可能的三元组和为 0 。

提示:

  • 3 <= nums.length <= 3000
  • -105 <= nums[i] <= 105

思路:

  • 先将数组从小到大排序。
  • 循环每个元素,然后在数组中查找符合题意的结果集。
  • 声明两个指针l ,r。l 表示循环中当前元素的后一个元素 ,r 指针表示数组最后一个元素。
  • 去重:
    • 如果当前元素和上一个元素相同,说明上次循环已经查找过,跳过本次循环,避免重复。
    • 如果l 指针和 l 后一位元素相同,则向右移动 l
    • 如果 r 指针和 r 指针前一个元素相同,则向左移动 r 指针

代码

const threeSum = (nums) => {
        if (nums.length <= 0) return [];
        nums.sort((a, b) => a - b); // 先将数据从小到大排序
        const result = []; // 声明结果
 
        for (let i = 0; i < nums.length; i++) {
          if (nums[i] > 0) break; // 如果从某个元素开始,值大于 0,则证明后面的三个数之和不可能等于 0, 直接结束循环
          let l = i + 1; // 声明左指针(当前元素后面的一个元素)
          let r = nums.length - 1; // 声明右指针
          
          if (i > 0 && nums[i] === nums[i - 1]) continue; // 如果 当前元素和前一个元素相同,说明是相同的查找结果,直接跳过本次循环,进行下一次循环。
 
          while (l < r) {
            const sum = nums[i] + nums[l] + nums[r]; // 计算三个元素的和
            if (sum === 0) { 
              result.push([nums[i], nums[l], nums[r]]);
              while (l < r && nums[l] === nums[l + 1]) { // 这里是为了取掉重复的情况
                l = l + 1;
              }
              while (l < r && nums[r] === nums[r - 1]) { // 同理,这里也是为了取掉重复的情况
                r = r - 1;
              }
              l++;
              r--;
            }
            if (sum < 0) { // 如果三数之和小于 0 ,则向右移动 l 指针,因为数组左边的元素小
              l = l + 1;
            }
            if (sum > 0) { // 如果三数之和大于 0. 则向左移动 r 指针
              r = r - 1;
            }
          }
        }
        return result;
      };