三数之和

给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。

注意:答案中不可以包含重复的三元组。

思路:根据两数之和,三数之和为具有多个target的两数之和,可以使用hash表或者对撞指针,方法比较明确,但三数之和难点在于结果去重。

使用hash表去重思路一直存在bug,因此先使用对撞指针。

对撞指针思路:

1、首先将数组排序,从小到大。

2、避免结果重复,只将负数和0作为target。

3、从数组首位开始,依次将当前数的相反数作为target,并指定其后数组左右两端作为左右指针。

4、时刻确保左指针小于右指针,判断左指针与右指针数加和是否等于target,若小于target,则说明左指针比较小,将左指针右移,若大于target,则说明右指针过大,将右指针左移。

5、若等于target,则找到目标,将三个数排好序添加到结果集中,然后循环判断左指针下一位是否与当前数相同,相同则左指针右移,然后循环判断右指针下一位是否与当前数相同,相同则左移,过滤掉相同的数,然后再左指针右移一位,右指针左移一位。

6、target一轮循环结束,需要循环判断下一位数是否与当前target相同,若相同则循环将相同的target过滤掉。

    public List<List<Integer>> threeSum(int[] nums) {
        //对撞指针
        int left;
        int right;
        int target;
        
        List<Integer> list = new ArrayList<>();
        List<List<Integer>> res = new ArrayList<>();
        
        if(nums.length<3){return res;}
        Arrays.sort(nums);
        
        for(int i=0;i<nums.length-1&&nums[i]<=0;i++){
            
            
            left = i+1;
            right = nums.length-1;
            target = -nums[i];
            
            while(left<right){
               
                
                if(left<right&&nums[left]+nums[right]==target){
                    list = new ArrayList<>();
                    list.add(nums[left]);
                    list.add(nums[right]);
                    list.add(-target);
                    Collections.sort(list);
                    res.add(list);
                    
                    while(left<right&&nums[left]==nums[left+1]){left++;}
                    while(left<right&&nums[right]==nums[right-1]){right--;}
                    
                    left++;
                    right--;
                }else if(left<right&&nums[left]+nums[right]<target){
                    left++;
                }else if(left<right){
                    right--;
                }
            }
            
            while(i<nums.length-1&&nums[i]==nums[i+1]){i++;}
            
        }
       
        return res;
    }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值