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题解 画手大鹏

相关推荐
skykun2 小时前
都2026年了还在说闭包吗?
javascript
饮水机战神2 小时前
小程序被下架后,我连夜加了个 "安全接口"
前端·javascript
柯南二号3 小时前
【大前端】 TypeScript vs JavaScript:全面对比与实践指南
前端·javascript·typescript
ting_zh3 小时前
导数、偏导数与梯度:机器学习数学基础
算法·基础数学
Larry_Yanan3 小时前
QML学习笔记(三十一)QML的Flow定位器
java·前端·javascript·笔记·qt·学习·ui
灰灰老师3 小时前
七种排序算法比较与选择[Python ]
java·算法·排序算法
秃头狂魔3 小时前
DAY1 数组一
算法
CM莫问3 小时前
推荐算法之粗排
深度学习·算法·机器学习·数据挖掘·排序算法·推荐算法·粗排
拉不动的猪3 小时前
从底层逻辑和实用性来分析ref中的值为什么不能直接引用
前端·javascript·面试