力扣15(Java)-三数之和(中等)
题目:
给你一个整数数组 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)-三数之和(中等)的更多相关文章
- 【LeetCode】15. 3Sum 三数之和
作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 个人公众号:负雪明烛 本文关键词:3sum, 三数之和,题解,leetcode, 力扣,P ...
- [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 ...
- LeeCode数组第15题三数之和
题目:三数之和 内容: 给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组. 注意:答案中 ...
- 【LeetCode】15、三数之和为0
题目等级:3Sum(Medium) 题目描述: Given an array nums of n integers, are there elements a, b, c in nums such t ...
- LeetCode 第15题-三数之和
1. 题目 2.题目分析与思路 3.思路 1. 题目 给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且 ...
- [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 ...
- 力扣 ——4Sum (四数之和)python 实现
题目描述: 中文: 给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值与 targe ...
- Leetcode(15)-三数之和
给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组. 注意:答案中不可以包含重复的三元组. ...
- leetcode 刷题(数组篇)15题 三数之和 (双指针)
很有意思的一道题,值得好好思考,虽然难度只有Mid,但是个人觉得不比Hard简单 题目描述 给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b ...
- 【LeetCode 15】三数之和
题目链接 [题解] 先把n个数字升序排个序. 然后枚举三元组最左边的那个数字是第i个数字. 之后用两个指针l,r移动来获取三元组的第2个和第3个数字. (初始值,l=i+1,r = n-1); 如果a ...
随机推荐
- 摆脱鼠标操作 - vscode - vim Ctrl + hjkl 我定位为 上下翻半页和行头行尾
为什么 摆脱鼠标操作 - vscode - vim Ctrl + hjkl 我定位为 上下翻半页和行头行尾 翻页和当前行的开头结尾 我觉得都是高频操作 实现 settings.json 还附加了几个其 ...
- 摆脱鼠标系列 - vscode - 跳转到下一个文件 Ctrl(右边) + PageDown 这个很常用
为什么 摆脱鼠标系列 - vscode - 跳转到下一个文件 Ctrl(右边) + PageDown 这个很常用 右边Ctrl 就可以单手操控了 这个频率很高
- 解决Windows下json.hpp中文乱码问题
文中使用的是 json 库,整个库的代码由一个单独的头文件json.hpp组成,用普通的C++11编写的.它没有库,没有子项目,没有依赖关系,没有复杂的构建系统,使用起来很方便. 先引用头文件和命名空 ...
- c语言中的指针,数组和结构体结合的一个经典案例
一 你真正懂了C语言了吗? 很多人刚把c语言用了两年,就以为很懂,等遇到稍微深层次一点的问题,就卡住了.这里,有一个问题,可以考察你对这三者理解如何. 二 一个例子: #include <std ...
- Shell脚本自动下载FTP文件上传到S3
1. shell脚本下载 #!/bin/bash #用户名 USER=xxx #密码 PASSWORD=xxx #下载文件临时目录 SRCTDIR=/approveform/uat/tempin #S ...
- Java线上诊断神器Arthas:常用命令详解!
有关Arthas基本介绍.安装部署.arthas idea插件在上篇文章已经介绍过,这里就不在重述. 文章地址:Java诊断工具Arthas:开篇之watch实战 上篇重点讲了 watch 命令.这篇 ...
- 低代码平台前端的设计与实现(二)构建引擎BuildEngine切面处理设计
上一篇文章,我们介绍了如何设计并实现一个轻量级的根据JSON的渲染引擎,通过快速配置一份规范的JSON文本内容,就可以利用该JSON生成一个基础的UI界面.本文我们将回到低开的核心-页面拖拉拽,探讨关 ...
- C#开发计算器类库
C#开发计算器类库:开发中所涉及到有虚方法,继承,简单工厂等基础知识(编程借鉴'小菜变成成长记'https://www.jb51.net/article/2851.htm) 1.创建父类:计算(Ope ...
- C++ memcpy、memmove
函数原型: void *memcpy(void *dest, const void* src, size_t count ); void *memmove(void *dest, const void ...
- springboot 低于 2.6 版本设置 SameSite=None,springboot 1.x set SameSite=none in embedded tomcat
speingboot 使用自带的 tomcat 运行,设置 SameSite. springboot 过低的版本没有 SameSite 的属性设置,升级到 1.5.22 版本后,虽然 Rfc6265C ...