要求:
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。 注意:答案中不可以包含重复的三元组。
案例:
给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]
思路:
-
先对数组进行排序
-
固定三个指针中最左边的那个指针k,另外两个指针i,j分别指向剩余部分的两端
-
i,j交替向中间移动,记录下对于每个固定指针k的前提下,满足nums[k]+nums[i]+nums[j]==0的组合
1. nums[k]>0时,直接break跳出循环。因为后面的数再加肯定大于0 2.当k>0且nums[k]==nums[k-1]时,跳过此元素,避免重复 3.正常情况下按如下规则移动指针: 1. sum<0时,i++,并跳过所有重复的nums[i]; 2. s>0时,j--,并跳过重复的nums[j]; 3. sum=0时,记录[k,i,j]至res,并执行i++和j--,并跳过所有重复的nums[i],nums[j],防止重复记录组合。
代码:
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> ans = new ArrayList<>();
int len = nums.length;
Arrays.sort(nums);
for (int k = 0; k < len-2; k++) {
if (nums[k] > 0) break;
if (k > 0 && nums[k]==nums[k+1]) continue;//略过后面的操作,直接把指针k后移
int i = k+1;
int j = len-1;
while (i<j) {
int sum = nums[k]+nums[i]+nums[j];
if (sum == 0) {
ArrayList<Integer> list = new ArrayList<>();
list.add(nums[k]);
list.add(nums[i]);
list.add(nums[j]);
ans.add(list);
while (i<j && nums[i]==nums[i+1]) i++;
while (i<j && nums[j]==nums[j-1]) j--;//略过重复的数字
i++;
j--;//i,j记录之后都要移动,因为下一个组合的数字必然不会再是这三个数的组合了
}
else if(sum<0) i++;
else if(sum>0) j--;
}
}
return ans;
}
}