【中等】算法:三数之和

85 阅读1分钟

三数之和

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第8天,点击查看活动详情

三数之和

算题

给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素,a,b,c , 使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。

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

示例 1:

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

示例 2:

输入: nums = []
输出: []

示例 3:

输入: nums = [0]
输出: []

提示:

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

解析

言简意赅,完成这个需求就必须实现:

1. 三数之和等于0

2.不可出现重复的数字组合(可出现重复的数字)

先看第二个需求:不重复,这就表示我们不能出现三个同样的数字组成的数组,为了避免这种情况,最简单的实现就是排序,排序之后相同的数字必然是相邻的,那么在遍历的时候判断跳过即可。三数之和等于0,可以在遍历的同时使用双指针,每一次遍历循环使用双指针去相加:(以从小到大排序为例)

1. 相加等于0,那么结果 + 1

2. 相加大于0,那么右置针左移

3. 相加小于0,那么左指针右移

代码实现:

var threeSum = function (nums) {
  let result = []; // 结果数组
  let arr = nums.sort((a, b) => a - b); // 排序
  for (let i = 0; i < arr.length; i++) { // 循环遍历数组
    if (arr[i] > 0) break; // 如果当前数字大于0,则跳出循环
    if (i > 0 && arr[i] === arr[i - 1]) continue; // 如果当前数字与上一个数字相同,则跳过,避免重复
    let left = i + 1; // 左指针
    let right = arr.length - 1; // 右指针
    while (left < right) { // 左右指针循环
      let sum = arr[i] + arr[left] + arr[right]; // 当前数字与左右指针的和
      if (sum === 0) { // 如果和为0
        result.push([arr[i], arr[left], arr[right]]); // 将结果添加到结果数组
        while (left < right && arr[left] === arr[left + 1]) left++; // 如果左指针与左指针+1相等,则左指针+1
        while (left < right && arr[right] === arr[right - 1]) right--; // 如果右指针与右指针-1相等,则右指针-1
        left++; // 左指针+1
        right--; // 右指针-1
      } else if (sum > 0) { // 如果和大于0
        right--; // 右指针-1
      } else { 
        left++; // 左指针+1
      }
    }
  }
  return result;
}; 

附上提交结果:

image.png