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

相关推荐
浅念-几秒前
C ++ 智能指针
c语言·开发语言·数据结构·c++·经验分享·笔记·算法
不染尘.2 分钟前
最小生成树算法
开发语言·数据结构·c++·算法·图论
哈__12 分钟前
ReactNative项目OpenHarmony三方库集成实战:react-native-device-info
javascript·react native·react.js
Klong.k15 分钟前
判断是不是素数题目
数据结构·算法
庄小焱16 分钟前
React——React基础语法(2)
前端·javascript·react.js
QQsuccess16 分钟前
AI全体系保姆级详讲——第一部分:了解AI基本定义
人工智能·算法
终端鹿18 分钟前
Vue3 核心 API 深度解析:ref / reactive / computed / watch
前端·javascript·vue.js
_日拱一卒19 分钟前
LeetCode:移动零
算法·leetcode·职场和发展
console.log('npc')25 分钟前
partial在react接口定义中是什么意思
前端·javascript·typescript
SuperEugene26 分钟前
前端 utils 工具函数规范:拆分 / 命名 / 复用全指南,避开全局污染等高频坑|编码语法规范篇
开发语言·前端·javascript