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

相关推荐
吃饺子不吃馅4 分钟前
⚡️ Zustand 撤销重做利器:Zundo 实现原理深度解析
前端·javascript·github
m0_591338919 分钟前
day8鹏哥C语言--函数
c语言·开发语言·算法
_OP_CHEN13 分钟前
算法基础篇:(二)基础算法之高精度:突破数据极限
算法·acm·算法竞赛·高精度算法·oj题
一只老丸15 分钟前
HOT100题打卡第30天——技巧
算法
Bi_BIT26 分钟前
代码随想录训练营打卡Day38| 动态规划part06
算法·动态规划
手握风云-1 小时前
回溯剪枝的“减法艺术”:化解超时危机的 “救命稻草”(三)
算法·剪枝
元亓亓亓1 小时前
LeetCode热题100--46. 全排列--中等
算法·leetcode·职场和发展
远航_1 小时前
10 个被严重低估的 JS 特性,直接少写 500 行代码
前端·javascript
小高0071 小时前
当前端面临百万级 API 请求:从"修 CSS 的"到架构师的进化之路
前端·javascript·面试
LateFrames1 小时前
使用 Winform / WPF / WinUI3 / Electron 实现异型透明窗口
javascript·electron·wpf·winform·winui3