目录
三数之和
描述
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例 1
输入:nums = [-1,0,1,2,-1,-4] 输出:[[-1,-1,2],[-1,0,1]]
示例 2
输入:nums = [] 输出:[]
示例 3
输入:nums = [0] 输出:[]
提示
方法:双指针
本题看似可以用哈希表做,但是去重操作比较麻烦,所以本题的最好方法是双指针。
首先我们还是对数组进行排序,固定3个指针中最左边数字的指针k,然后让双指针i,j在开区间(k,nums.length)两端交替往中间移动,记录每个满足条件的下标组合。
1、当nums[k]>0时,此时nums[k]<=nums[i]<=nums[j],所以三者和一定大于0,直接跳出
2、当k>0且nums[k]==nums[k-1]时,此时我们已经将nums[k-1]的所有满足要求的组合放入到结果中,如果继续找nums[k]的组合,那么会得到重复组合,所以此时我们直接continue
3、i和j分别位于(k,nums.length)两端,当i<j时计算s=nums[k]+nums[i]+nums[j],并按照如下规则进行移动:
- 当s<0时,i++并跳过所有重复的nums[i]
- 当s>0时,j--并跳过所有重复的nums[j]
- 当s==0时,记录[k,i,j]到res中,i++并跳过所有重复的nums[i],j--并跳过所有重复的nums[j]
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) break;//若当前元素大于0,后面的也不用遍历了
if(k > 0 && nums[k] == nums[k - 1]) continue;//对a元素进行去重
int i = k + 1, 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]);//i指针右移,并跳过所有重复的nums[i]
} else if (sum > 0) {
while(i < j && nums[j] == nums[--j]);//j指针左移,并跳过所有重复的nums[j]
} else {
res.add(new ArrayList<Integer>(Arrays.asList(nums[k], nums[i], nums[j])));//记录结果
while(i < j && nums[i] == nums[++i]);//i指针右移,并跳过所有重复的nums[i]
while(i < j && nums[j] == nums[--j]);//j指针左移,并跳过所有重复的nums[j]
}
}
}
return res;
}
}