leetcode刷题记录-15. 三数之和

547 阅读1分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

前言

今天的题目为中等,对于能通过数组遍历解答的题目,如果遍历的数字过大,那么就需要去考虑如何优化时间复杂度,优化的方法很多,对于不同的情况,有不同的方法适用。

每日一题

题目为 15. 三数之和,难度为中等

  • 给你一个包含 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

题解

数组遍历

双指针优化

题目要求出三个数,首先当然可以暴力性的三重循环遍历所有可能,但是这样太耗时,会导致超时,那么我们就需要想个方法来进行优化。

对于双重循环找满足条件的数字,马上就能够想到双指针,那么我们就可以用双指针来查找其中的两个数字,那么第三个数,我们可以将它固定,然后去寻找满足条件的后两个数,这样相当于每次只是去查找后面的两个数,只是没每次的要求都不同。

循环解题

首先我们将数组进行排序,然后就可以去固定第一位数,对后面的 n-1 个数做双指针的循环

先将数组进行排序

image.png

然后从第一个数开始固定为 i 后面的两端分别为 L 和 R

image.png

如果 i 是 大于0的,那说明不存在三数相加等于0的情况了,直接结束循环

如果三数相加的结果小于零,说明结果过小,那么 L++,反之 R++

碰到了 三数相加 等于零的情况时,说明这正是我们需要的三个数,将其加入结果数组当中

循环结束完全部的数组之后,就可以得到我们想要的答案了。

/**
 * @param {number[]} nums
 * @return {number[][]}
 */
var threeSum = function (nums) {
  let ans = [];
  const n = nums.length;
  if (nums == null || n < 3) return ans;
  nums.sort((a, b) => a - b);
  for (let i = 0; i < n; i++) {
    if (nums[i] > 0) break;
    if (i > 0 && nums[i] == nums[i - 1]) continue;
    let L = i + 1;
    let R = n - 1;
    while (L < R) {
      const sum = nums[i] + nums[L] + nums[R];
      if (sum == 0) {
        ans.push([nums[i], nums[L], nums[R]]);
        while (L < R && nums[L] == nums[L + 1]) {
          L++;
        }
        while (L < R && nums[R] == nums[R - 1]) {
          R--;
        }
        L++;
        R--;
      } else if (sum < 0) L++;
      else if (sum > 0) R--;
    }
  }
  return ans;
};

image.png