原题戳 力扣
欢迎关注我的刷题专栏 zhangyixing1007/leetcode
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例:
给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为: [ [-1, 0, 1], [-1, -1, 2] ]
来源:力扣(LeetCode) 链接:力扣 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
划重点:答案中不可以包含重复的三元组。
我们来理解一下这句话。
Q1:nums=[-1,-1,2], ans=[[-1,-1,2]]是重复的三元组嘛?
A1:显然不是,这里只有一组三元组,虽然这组三元组中有两个-1,但,这也不叫重复。
Q2:nums=[-1,-1,-1,2], ans=?
A2:ans=[[-1,-1,2]],这里ans中的-1无论是取的第0/1/2个都没有关系。
Q1告诉我们想要避免重复值,显然不是不允许三元组中存在重复的元素。这意味着,我们不能简单粗暴直接对数组去重。
Q2告诉我们无论相同的元素有多少个,它们的三元组表示都不能重复--看起来可以用set直接对三元组去重?
是的,但还可以更加简单。
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
if(nums==null||nums.length<3) return new ArrayList<>();
List<List<Integer>> ans=new ArrayList<>();
int n=nums.length;
Arrays.sort(nums);
for(int i=0; i+2<n; i++){
if(i>0 && nums[i]==nums[i-1]) continue;//对i去重
if(nums[i]>0) break;//一开始就大了 没有必要继续了
if(nums[i]+nums[n-2]+nums[n-1]<0) continue;//说明i小了 直接跳出本次循环
// left,right双指针,结果<target则left右移,>target则right左移
int left=i+1, right=n-1;
while(left<right){
int sum=nums[i]+nums[left]+nums[right];
if(sum==0){
ans.add(Arrays.asList(nums[i], nums[left], nums[right]));
while(left<right && nums[left]==nums[left+1]) left++;
left++;//之前left指向的是最后一个重复值 所以这里要再来一次到达新值
while(right>left && nums[right]==nums[right-1]) right--;
right--;//之前right指向的是最后一个重复值 所以这里要再来一次到达新值
}else if(sum<0){
left++;
}else{
right--;
}
}
}
return ans;
}
}
在这基础上,我们还可以做四数之和,就是需要多一层循环。详见
zhangyixing1007:20201005 每日一题 0018 四数之和zhuanlan.zhihu.com以上。