当前位置: 首页 > news >正文

LeetCode Hot 100:15. 三数之和

题目

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

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

示例 1:

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

示例 2:

输入:nums = [0,1,1]
输出:[]
解释:唯一可能的三元组和不为 0 。

示例 3:

输入:nums = [0,0,0]
输出:[[0,0,0]]
解释:唯一可能的三元组和为 0 。

解析

为方便双指针以及跳过相同元素,先把 nums 排序。

枚举 nums[i],问题变成 nums[j]+nums[k]=−nums[i]。

题目要求答案中不能有重复的三元组。如何避免重复?

在外层循环中,如果发现 nums[i]=nums[i−1],那么 nums[i] 与后面两个数组成的和为 0 的三元组,nums[i−1] 也能组成一模一样的三元组,这就重复了,所以遇到 nums[i]=nums[i−1] 的情况,直接 continue。

在内层循环中,当三数之和等于 0 时,为避免把相同的三元组计入答案,跳过后续相同的 nums[j] 和 nums[k](也可以只跳过相同的 nums[j])。

优化
优化一:如果 nums[i] 与后面最小的两个数相加 nums[i]+nums[i+1]+nums[i+2]>0,那么后面不可能存在三数之和等于 0,break 外层循环。

优化二:如果 nums[i] 与后面最大的两个数相加 nums[i]+nums[n−2]+nums[n−1]<0,那么内层循环不可能存在三数之和等于 0,但继续枚举,nums[i] 可以变大,所以后面还有机会找到三数之和等于 0,continue 外层循环。

------------------------------------------------

作者:灵茶山艾府
链接:https://leetcode.cn/problems/3sum/
来源:力扣(LeetCode)

答案

/*** @param {number[]} nums* @return {number[][]}*/
var threeSum = function(nums) {nums.sort((a,b) => a-b);    //排序const ans = [];const len = nums.length;for(let k=0; k<len-2; k++) {//和前一个数相同,那么后面能组成0的两个数的答案相同,跳过该数if(k>0 && nums[k] === nums[k-1]) continue;//和后面两个最小的数之和都大于0,不可能找到等于0的两个数,跳出for循环if(nums[k] + nums[k+1] + nums[k+2] > 0) break;//和最后两个最大的数之和都小于0,内层循环固定位的数太小,回到外层循环找更大的数if(nums[k] + nums[len-2] + nums[len-1] < 0) continue;let i = k+1, j=len-1;while(i < j) {const s = nums[k] + nums[i] + nums[j];if(s < 0) {    //换更大的加数i++;} else if(s > 0) {    //换更小的加数j--;} else {ans.push([ nums[k], nums[i], nums[j]]);    //等于0,加入答案for(i++; i<j && nums[i] === nums[i-1]; i++);    //跳过重复的数for(j--; j<i && nums[j] === nums[j+1]; j--);    //跳过重复的数}}}return ans;
};

复杂度分析

时间复杂度:O(n^2),其中 n 为 nums 的长度。排序 O(nlogn)。外层循环枚举第一个数,做法是 O(n) 双指针。所以总的时间复杂度为 O(n^2 )。
空间复杂度:O(1)。返回值不计入。忽略排序的栈开销。

------------------------------------------------

作者:灵茶山艾府
链接:https://leetcode.cn/problems/3sum/
来源:力扣(LeetCode)

http://www.dtcms.com/a/306874.html

相关文章:

  • Nuxt3 全栈作品【通用信息管理系统】角色管理(含配置权限 -- 菜单权限 vs 操作权限)
  • 差分数组前缀和优化,降低时间复杂度
  • vue+elementui+vueCropper裁剪上传图片背景颜色为黑色解决方案
  • ‌我的第一个开源项目:跃动的心
  • 物流分拣漏检率↓78%!陌讯动态光流算法在包裹移动识别的技术突破
  • GCC链接技术深度解析:性能与空间优化
  • [mcp: McpSchema]-源码分析
  • 第1课:向量与矩阵运算
  • 搭建实时足球比分系统从零到一的实战指南
  • Day 4-1: 机器学习算法全面总结
  • 全新AI工具小程序源码 全开源(源码下载)
  • 深入浅出:在 Spring Boot 中构建实时应用 - 全面掌握 WebSocket
  • 解决 Docker 报错 “exec: no such file or directory”
  • 文件权限值的表示方法
  • PHP/Java/Python实现:如何有效防止恶意文件上传
  • Go 语言make函数
  • 输电线路绝缘子泄漏电流在线监测装置的技术解析与应用价值
  • Python读取获取波形图波谷/波峰
  • Directory Opus 使用优化
  • 30道JS高频经典笔试题集合+详解(一)
  • 视觉系统引导冲床冲压:工业自动化的“智能之眼”
  • Dify 从入门到精通(第 4/100 篇):快速上手 Dify 云端:5 分钟创建第一个应用
  • AI培训项目《人工智能大模型应用工程师》课程学习大纲分享!
  • 【sklearn(01)】数据集加载、划分,csv文件创建,特征工程,无量纲化
  • 【编号65】广西地理基础数据(道路、水系、四级行政边界、地级城市、DEM等)
  • 我的世界模组开发教程——资源(1)
  • JeecgBoot(1):前后台环境搭建
  • C#_创建自己的MyList列表
  • 汽车电子控制系统开发的整体安全理念
  • SOA增益谱与ASE光谱的区别