LeetCode热题100——15.三数之和

题目描述

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

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

示例

scss 复制代码
输入: 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] 。
注意,输出的顺序和三元组的顺序并不重要。

提示:

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

题解

js 复制代码
/**
 * @param {number[]} nums
 * @return {number[][]}
 */
var threeSum = function (nums) {
    let ans = [];
    const len = nums.length;
    if (nums == null || len < 3) return ans;
    nums.sort((a, b) => a - b);
    for (let i = 0; i < len; i++) {
        if (nums[i] > 0) break;
        if (i > 0 && nums[i] == nums[i - 1]) continue;
        let L = i + 1;
        let R = len - 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;
};

首先通过sort()对数组进行排序,从而方便后续的双指针移动和去重

最外层通过一个for循环遍历数组来获取三元组的第一个数。 for循环里面设定两个指针L,R以及变量sum.L指针从i的右侧开始(较小),R指针从数组末尾开始(最大),sum用来计算当前的和。

内层while循环,条件为L<R以免去重复,寻找能满足nums[i]+nums[L]=nums[R]的组合

  • 若满足sum=0条件,存储当前三元组,然后L向右移动,R同时向左移动以寻找下一个满足条件的。(只移动一个必定不会满足sum为0)
  • 若sum<0,当前和较小,L向右移动以获得较大的值
  • 若sum>0,当前和较大,R向左移动以获得较小的值

优化

  • 最开始先检查数组元素数量,如果<3必然不存在三元组满足条件,直接返回
  • while循环前先检查当前的nums[i],如果>0,因为L,R指针都大于i,数组按大小排序,则必然不存在满足条件的三元组,跳过当前循环。
  • while循环前再检查当i不指向第一个元素时,i是否和前一个i-1指向的值相等,如果相等,结束当前循环避免重复计算。
  • 若当前sum==0时,通过while循环里的条件判断: 若L<R且L和L+1/R和R-1指向的值相等时,执行L++/R--操作以跳过L+1/R-1。此处使用while循环代替if判断来实现连续去重

时间,空间复杂度

时间复杂度O(N^2)

排序的复杂度为 O(NlogN)。

外层if循环固定 i 运行 N 次。

内层 while 循环的双指针 L 和 R 共同遍历的次数为 O(N)。

总复杂度为 O(NlogN)+O(N×N)=O(N^2)。

空间复杂度:O(logN) 或 O(N)

取决于 JavaScript 内部排序算法所需的额外空间。如果是快速排序,通常为 O(logN);如果是归并排序,则为 O(N)。

参考题解:LeetCode题解 画手大鹏

相关推荐
芳草萋萋鹦鹉洲哦3 小时前
【elemen/js】阻塞UI线程导致的开关卡顿如何优化
开发语言·javascript·ui
1***s6323 小时前
Vue图像处理开发
javascript·vue.js·ecmascript
AndrewHZ3 小时前
【图像处理基石】如何在图像中提取出基本形状,比如圆形,椭圆,方形等等?
图像处理·python·算法·计算机视觉·cv·形状提取
蓝牙先生4 小时前
简易TCP C/S通信
c语言·tcp/ip·算法
槁***耿4 小时前
JavaScript在Node.js中的事件发射器
开发语言·javascript·node.js
一叶茶4 小时前
移动端平板打开的三种模式。
前端·javascript
U***49834 小时前
JavaScript在Node.js中的Strapi
开发语言·javascript·node.js
老前端的功夫4 小时前
前端浏览器缓存深度解析:从网络请求到极致性能优化
前端·javascript·网络·缓存·性能优化
颜酱6 小时前
Monorepo 架构以及工具选型、搭建
前端·javascript·node.js
X***48966 小时前
JavaScript在Node.js中的Nx
javascript·node.js·vim