三数之和
给你一个整数数组 nums
,判断是否存在三元组 [nums[i], nums[j], nums[k]]
满足 i != j
、i != k
且 j != k
,同时还满足 nums[i] + nums[j] + nums[k] == 0
。请
你返回所有和为 0
且不重复的三元组。
注意: 答案中不可以包含重复的三元组
示例1
**输入:**nums = [-1,0,1,2,-1,-4]
输出: [[-1,-1,2],[-1,0,1]]
解释:
nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。 nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。 nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。 不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。 注意,输出的顺序和三元组的顺序并不重要。
示例2:
**输入:**nums = [0,1,1]
输出: []
解释: 唯一可能的三元组和不为 0 。
示例3:
**输入:**nums = [0,0,0]
输出: [[0,0,0]]
解释: 唯一可能的三元组和为 0 。
分析:
先对数组进行排序,然后枚举其中的一个数nums[i],然后问题就变成了再剩下的数中找到两个数的和等于-nums[i]。为了避免重复元素,需要在枚举的时候跳过所有重复元素。
- 如果三数之和小于0,左指针右移,使总和增大
- 如果三数之和大于0,右指针左移,使总和减少
- 如果三数之和等于0,将三个数加入集合
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> lis= new ArrayList<>();
int len=nums.length;
if(len<3||nums==null){
return lis;
}
Arrays.sort(nums);
for (int a=0;a<len;a++){
//经过排序,如果首位数字大于0,三数之和一定大于0
if(nums[a]>0){
break;
}
//a去重
if(a>0 && nums[a]==nums[a-1]){
continue;
}
//定义初始位置
int c=len-1;
int b=a+1;
while(b<c){
//b去重
if(b>a+1 && nums[b]==nums[b-1]) {
b++;
continue;
}
while(b<c && nums[b]+nums[c]+nums[a]<0){
b++;
}
while(b<c && nums[b]+nums[c]+nums[a]>0){
c--;
}
if(b==c){
break;
}
if(nums[a]+nums[b]+nums[c]==0){
lis.add(Arrays.asList(nums[a],nums[b],nums[c]));
}
b++;
}
}
return lis;
}
}