题目:

给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != 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 。

提示:

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

来源:力扣(LeetCode)
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路:

双指针

参考:代码随想录的文字讲解  && 代码随想录的视频讲解

  • 需要求的是数字而不是索引,可以先将数组排序,利用一层for循环,从下标0开始遍历数组元素,即nums[i],再定义双指针从left =  i+1,right = nums.length - 1开始往中间靠拢,寻找sum = nums[i] + nums[left] + nums[right]
  • 如果sum > 0, 说明和大了,应该减小,则移动右指针使其数字变小,即right--;
  • 如果sum < 0,说明和小了,应该增大,则移动左指针使其数字变大,即left++;
  • 如果sum == 0, 说明找到了一个符合题意的三元组,即加入结果集。

细节问题:

①答案中不应该包含重复的三元组[三元组内的数字可以重复],如果nums[i]有重复的应该在怎么去重,是判断nums[i] == nums[i+1] 还是nums[i] == nums[i-1]的时候跳过当前数字呢?

例如:示例1中的nums = [-1,0,1,2,-1,-4],排序后nums = [-4,-1,-1,0,1,2]

  • 如果判断 nums[i] == nums[i+1] 的时候跳过:nums[1] == nums[2],有[-1,-1,2]和[-1,0,1]这两个符合要求的三元组,这时候跳过,下一步遍历到nums[2]== -1时,就只有[-1,0,1],总体就会跳过[-1,-1,2这个符合要求的三元组。
  • 如果判断 nums[i] == nums[i-1] 的时候跳过:遍历到nums[1] == -1的时候有[-1,-1,2]和[-1,0,1]这两个符合要求的三元组,下一步遍历到nums[2]== -1时,nums[2] == nums[1]时,就有[-1,0,1]这时候与nums[1]得到的三元组重复了,就需要跳过了。

②左右指针的去重应该放在找到第一个三元组之后去重:例如:[0,0,0,0,0]

如果按照下面这样写,那么就不会得到任何一个满足条件的三元组,但是实际上是有一个符合条件的三元组的[0,0,0],所以bc的去重应该写在得到第一个符合要求的三元组后面。

while (left < right){
//如果将bc去重逻辑放在while后面
while (left < right && nums[left] == nums[left + 1]) left++;
while (left < right && nums[right] == nums[right - 1]) right--;
.....
}

代码:

 1 class Solution {
2 public List<List<Integer>> threeSum(int[] nums) {
3 ArrayList<List<Integer>> ans = new ArrayList<>();
4 Arrays.sort(nums);
5 for (int i = 0; i < nums.length; i++){
6 //如果第一个数(最小的数)都大于0,后面相加只会更大不会等于0
7 if (nums[i] > 0) return ans;
8 //去重,避免重复的三元组
9 if (i > 0 && nums[i] == nums[i-1]) continue;
10 int left = i + 1, right = nums.length - 1;
11 while (left < right){
12 int sum = nums[i] + nums[left] + nums[right];
13 //如果和大于0,让和减小移动右指针
14 if (sum > 0){
15 right--;
16 }else if (sum < 0){
17 //和小于0,让和变大,移动左指针
18 left++;
19 }else{
20 //和等于0,找到一个三元组添加进结果
21 ans.add(Arrays.asList(nums[i], nums[left], nums[right]));
22 //去除左右指针后面和前面的重复元素,例如[-1,-1,-1,0,1,1,1]
23 while (left < right && nums[left] == nums[left + 1]) left++;
24 while (left < right && nums[right] == nums[right - 1]) right--;
25 left++;
26 right--;
27 }
28 }
29 }
30 return ans;
31 }
32 }

小知识:

Arrays.asList(): 该方法是将数组转化成List集合的方法。

  • 用此方法得到的List的长度是不可改变的;
  • 不支持add()、remove()、clear()等方法;
  • 将数组转换为ArrayList:List list = new ArrayList<>(Arrays.asList("a", "b", "c"))

力扣15(Java)-三数之和(中等)的更多相关文章

  1. 【LeetCode】15. 3Sum 三数之和

    作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 个人公众号:负雪明烛 本文关键词:3sum, 三数之和,题解,leetcode, 力扣,P ...

  2. [LeetCode] 15. 3Sum 三数之和

    Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all un ...

  3. LeeCode数组第15题三数之和

    题目:三数之和 内容: 给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组. 注意:答案中 ...

  4. 【LeetCode】15、三数之和为0

    题目等级:3Sum(Medium) 题目描述: Given an array nums of n integers, are there elements a, b, c in nums such t ...

  5. LeetCode 第15题-三数之和

    1. 题目 2.题目分析与思路 3.思路 1. 题目 给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且 ...

  6. [leetcode]15. 3Sum三数之和

    Given an array nums of n integers, are there elements a, b, c in nums such that a + b + c = 0? Find ...

  7. 力扣 ——4Sum (四数之和)python 实现

    题目描述: 中文: 给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值与 targe ...

  8. Leetcode(15)-三数之和

    给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组. 注意:答案中不可以包含重复的三元组. ...

  9. leetcode 刷题(数组篇)15题 三数之和 (双指针)

    很有意思的一道题,值得好好思考,虽然难度只有Mid,但是个人觉得不比Hard简单 题目描述 给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b ...

  10. 【LeetCode 15】三数之和

    题目链接 [题解] 先把n个数字升序排个序. 然后枚举三元组最左边的那个数字是第i个数字. 之后用两个指针l,r移动来获取三元组的第2个和第3个数字. (初始值,l=i+1,r = n-1); 如果a ...

随机推荐

  1. 线上机器 swap 过高导致告警

    哈喽大家好,我是咸鱼. 今天收到了一个告警,说有台服务器上的 swap 过高,已经用了 50% 以上了. 登录机器查看一下内存以及 swap 的使用情况. [root@localhost ~]# fr ...

  2. Linux 服务器Python后台运行服务(ssh断开不退出)

    壹: 最近用python搭建一个物联网数据存储的微服务,部署到ubuntu上去,所以,python后台运行是一个必不可少的环节. 贰: 这个只需要是一个命令即可: 命令1(记录所有日志): nohup ...

  3. Github账号开启账号双重验证

    原文: Github开启双重验证 - Stars-One的杂货小窝 今天在浏览开源项目的时候,突然Github有个提示我要在9月18日前开启双重验证,说是不完成的话,到时候的Github账号会受到限制 ...

  4. RTMP录屏直播屏幕数据获取与MediaCodec编码

    目录 前言 RTMP直播实现流程 视频采集--MediaProjection 编码--MediaCodec 音频采集--AudioRecord RTMP音频包数据 RTMP视频数据 前言 本文介绍的是 ...

  5. 大年学习linux(第二节---磁盘管理)

    二.磁盘管理 文件系统配置文件 /etc/filesystems: 系统指定的测试挂载文件系统类型 /proc/filesystems: linux 系统已经加载的文件系统类型 /lib/module ...

  6. 直播预告:面对技术带来的新机遇,CG人如何腾飞?

    "新锐先锋,玩转未来"--首届实时染3D动画创作大赛由瑞云科技主办,英伟达.青椒云.3DCAT实时渲染云协办,戴尔科技集团.Reallusion.英迈.万生华态.D5渲染器.中视典 ...

  7. csproj技巧,以及使用其他类库冲突,以及引入第三方UI方式

    1.在项目中我们经常写 string? Message{get;set;} 明明是引用类型,它底下还是会出现波浪线,我们可以打开csproj 找到Nullable将它改为disable,或者删除,它默 ...

  8. KingbaseES垃圾回收参数优化之maintenance_work_mem

    maintenance_work_mem 参数说明与vacuum过程 maintenance_work_mem , autovacuum_work_mem. 如果没有设置autovacuum_work ...

  9. 慢查询SQL排查

    转载请注明出处️ 作者:测试蔡坨坨 原文链接:caituotuo.top/c56bd0c5.html 你好,我是测试蔡坨坨. 在往期文章中,我们聊过数据库基础知识,可参考「数据库基础,看完这篇就够了! ...

  10. 电影数据集【可供机器学习附爬虫源码】(豆瓣、爱奇艺、IMDB、腾讯视频等)

    电影数据集(豆瓣.爱奇艺.IMDB.腾讯视频.搜狐.1905) 爬虫爬取豆瓣.爱奇艺.IMDB.腾讯视频.搜狐.1905网,电影数据. 获取方式:微信搜索关注[靠谱杨阅读人生]回复[电影]. 整理不易 ...