这是我参与2022首次更文挑战的第7天,活动详情查看:2022首次更文挑战
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。
输入:nums = [-1,0,1,2,-1,-4] 输出: [[-1,-1,2],[-1,0,1]]
!!!说实话,第一眼看到这到题的时候我是真的头痛,三个数相加等于零?之前我们有做过两数之和的题,那我们一样就可以看出来双指针吗!这个三个数,好家伙,三指针吗?这我也不会啊?
俗话说的好,只要我们不会一道题的时候,我们就去找他的暴解,再从暴解中寻找我们的正确答案
我们从图里看一下我们暴力是怎么解决的
三个循环嵌套加一个判断,想用它去做题,真的是痴心妄想,但是我们在这个解法中我们可以想到什么?
为什么暴力不可取,因为我们会重复的判断很多已经判断过的值,之后再去想一想我们的两数之和,先对数组排序,在进行双指针从两端移动,那我们三数之和,我们在中间再去添加一个指针,是不是就可以了?
那中间那个指针我们怎么去移动呢?
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
Arrays.sort(nums);
List<List<Integer>> res=new ArrayList<>();
for(int k=0;k<nums.length-2;k++){
if(nums[k]>0||nums[nums.length-1]<0) break;
if(nums[k]==nums[k+1]) continue;
int i=k+1;
int j=nums.length-1;
while(i<j){
int sum=nums[k]+nums[i]+nums[j];
if(sum<0){
i++;
}else if(sum>0){
j--;
}else{
res.add(new ArrayList<Integer>(Arrays.asList(nums[k], nums[i], nums[j])));
i++;
j--;
}
}
}
return res;
}
}
这就是我们的代码,但是它出错了,为什么呢?我们再去看一下题干,就是我们重复的三元我们是不需要的,那我们就需要去做一个去重的操作,那我们这一步填到哪里呢?
就是在我们指针移动的时候,如果我们指针移动到下一个元素是重复的时候我们就继续向前移动
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
//排序
Arrays.sort(nums);
List<List<Integer>> res=new ArrayList<>();
//这里-2的原因是因为我们是三个指针我们要留两个空位置
for(int k=0;k<nums.length-2;k++){
//先确定一下首位元素,如果最小的比0大或者最大的比0小,我们就不需要搞这些了
if(nums[k]>0||nums[nums.length-1]<0) break;
//对我们的起始位置K进行去重操作
if(k>0 && nums[k]==nums[k-1]) continue;
//定义左指针
int i=k+1;
//定义右指针
int j=nums.length-1;
while(i<j){
int sum=nums[k]+nums[i]+nums[j];
if(sum<0){
//左指针右移,去重
while(i<j&&nums[i]==nums[++i]);
}else if(sum>0){
//右指针左移,去重
while(i<j&&nums[j]==nums[--j]);
}else{
//添加到集合
res.add(new ArrayList<Integer>(Arrays.asList(nums[k], nums[i], nums[j])));
//两边指针向中间移动
while(i<j&&nums[i]==nums[++i]);
while(i<j&&nums[j]==nums[--j]);
}
}
}
return res;
}
}
!!!注意:如果有看完的自己写的小伙伴,注意这个i++和--i 如果我们使用的是i++ 我们获取的还是i的值,他就会出问题