题目:给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例:
给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]
思路:本文提供的排序+双指针思路
1.对数组进行升序排序。
2.对于数组中任意一个值,假设其索引为k,len为数组长度,那么我们需要在(k,len)内利用双指针判读是否存在两个数与索引为K的值和为0。
3.由于是排序后的数组,当三数之和大于0,说明最大值较大,将最右边指针左移一位,反之说明最小值较小,最左边指针右移一位。
下面是算法流程和一些边界的条件:
1.判断nums的长度为空或者长度小于3直接返回
2.排序数组
3.遍历数组
当nums[k]>0时,因为是排序数组,因此后面不存在可以使三数和为0的情况,直接跳出循环。
当K>len-3时,说明K后面不存在3个数,也跳出循环
当nums[k]=nums[k-1]时,避免存在相同值,k++,跳过后续操作
4.双指针选择符合的两个数
令左指针L=k+1,右指针R=len-1,当L<R,执行循环
当nums[L]+nums[R]+nums[k]=0时 添加到列表中,并且判断左边界和有边界下一个值是否和当前值相同,若相同跳过下一个值。寻找新的解
当nums[L]+nums[R]+nums[k]>0时 nums[R]过大 右指针左移
当nums[L]+nums[R]+nums[k]<0时 nums[L] 过小 左指针右移
public List<List<Integer>> threeSum(int[] nums) {
List list=new ArrayList<List>();
if(nums.length<3)return list; //当数组为空或者长度小于3 返回空
Arrays.sort(nums);
for(int index=0;index<=nums.length-3&&nums[index]<=0;index++){
if(index>0&&nums[index]==nums[index-1])//与上一个值相同 避免重复 跳过
continue;
int l=index+1;
int r=nums.length-1;
while(l<r)
{
if(nums[l]+nums[r]+nums[index]==0){
List t=new ArrayList<Integer>();
t.add(nums[index]);
t.add(nums[l]);
t.add(nums[r]);
list.add(t);
while(l<r&&nums[l]==nums[l+1])l++;//下一个位置值相同,跳过
while(l<r&&nums[r]==nums[r-1])r--;//同上
l++;
r--;
}
else if(nums[index]+nums[l]+nums[r]>0)r--;
else l++;
}
}
return list;
}