给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例:
给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]
最开始的思路:
- 从第一个数字开始建立Set a,保存曾经遍历过的数;
- 再建立一个临时Set b,保存第二个数字;
- 如果满足相加为0,如果第二个数字并且第三个数字都不在a和b中,就将第二个数字添加到b,并且记录结果。
这种思路的弊端:
过于重视不重复这个点,而且相加遍历有较大的重复度。
推荐思路:
- 给数组排序;
- 遍历 nums[i];
- 设置左指针l=i+1和右指针r=len-1;
条件: - 如果nums[i] == nums[i-1],跳过本轮循环;
- 如果nums[i]>0,结束算法;
- 如果三数之和为0,添加结果,l++,r--且值不重复;和大于0,r--;和小于0,l++;
- 如果l>=r,结束本轮循环。
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> ans = new ArrayList<>();
int len = nums.length;
if(len < 3) {
return ans;
}
Arrays.sort(nums);
for(int i=0;i<len-2;i++){
if(i>0 && nums[i] == nums[i-1]){
continue;
}
if(nums[i]>0) {
break;
}
int l = i+1;
int r = len-1;
while(l<r){
int sum = nums[i]+nums[l]+nums[r];
if(sum>0){
while(l<r && nums[r-1] == nums[r]) {
r--;
}
r--;
}else if(sum<0) {
while(l<r && nums[l+1] == nums[l]){
l++;
}
l++;
} else {
List<Integer> temp = new ArrayList<>();
temp.add(nums[i]);
temp.add(nums[l]);
temp.add(nums[r]);
ans.add(temp);
//ans.add(Arrays.asList(nums[i],nums[l],nums[r]));
while(l<r && nums[l+1] == nums[l]){
l++;
}
while(l<r && nums[r-1] == nums[r]) {
r--;
}
l++;
r--;
}
}
}
return ans;
}
}