开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 22 天,点击查看活动详情
第15题. 三数之和
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。
注意: 答案中不可以包含重复的三元组。
示例:
给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为: [ [-1, 0, 1], [-1, -1, 2] ]
思路
看到这题首先我也是想到要用哈希法,但是基本的思路写好了以后发现怎么都不对,原来又漏掉了题目中的条件:不重复的三元组。所以还要在原有的基础上去重,但是我想了一下,去重会很麻烦,所以就没有继续写,所以我们来开拓个新的方法吧。
看了代码随想录的题解后,我有了大致方向,这道题果然还是得用双指针。
首先要把对这个数组进行排序,然后我们就可以开始遍历了,因为排过序,所以第一个数一定是最小的,这时候我们判断:如果这个数大于零,那么这个数组就一定不成立了,这时候就可以直接返回。判断然这个后,还有一个重要点就是i和左右指针,如果nums[i]==nums[i-1]
就可以判断a是不是重复了,但是不能与i+1比较,因为我们只能规避过去犯过的错,而不能预知未来会犯的错。就是大概这个意思。
关于指针,如果三数之和大于零,就可以右指针左移,把最大的数变小,如果三数之和大于零,就可以左指针右移,把最小的数变大。
按照上面的思路,就可以写出代码啦。
解法
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> res=new ArrayList<>();
Arrays.sort(nums);
for(int i=0;i<nums.length;i++){
if(nums[i]>0) return res;
if(i>0 && nums[i]==nums[i-1]) continue;
int left=i+1;
int right=nums.length-1;
while(left<right){
int sum=nums[i]+nums[left]+nums[right];
if(sum>0){
right--;
}else if(sum<0){
left++;
}else{
res.add(Arrays.asList(nums[i],nums[left],nums[right]));
while(right>left && nums[right]==nums[right-1]) right--;
while(right>left && nums[left]==nums[left+1]) left++;
right--;
left++;
}
}
}
return res;
}
}