题目描述

给你一个包含 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]
输出:[] 

提示:
0 <= nums.length <= 3000
-105 <= nums[i] <= 105

题解

去重:每层循环各自不选择重复的数字。

三层循环(O(n^3^))

两层循环+二分查找(O(n^2^log^n^))

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        Arrays.sort(nums);

        List<List<Integer>>res=new ArrayList<>();
        for(int i=0;i<nums.length-2;++i){
        // 去重
            if(i>0&&nums[i-1]==nums[i]){
                continue;
            }
            for(int j=i+1;j<nums.length-1;++j){
        // 去重
                if(j>i+1&&nums[j-1]==nums[j]){
                    continue;
                }
                if(Arrays.binarySearch(nums,j+1,nums.length,(nums[i]+nums[j])*-1)>0){
                    List<Integer>list=new ArrayList<>();
                    list.add(nums[i]);
                    list.add(nums[j]);
                    list.add((nums[i]+nums[j])*-1);
                    res.add(list);
                }
            }
        }
        return res;
    }
}

两层循环+双指针(O(n^2^))

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        Arrays.sort(nums);

        List<List<Integer>>res=new ArrayList<>();
        for(int i=0;i<nums.length-2;++i){
        // 去重
            if(i>0&&nums[i-1]==nums[i]){
                continue;
            }
            for(int left=i+1,right=nums.length-1;left<right;){
                if(nums[left]+nums[right]+nums[i]==0){
                    List<Integer>list=new ArrayList<>();
                    list.add(nums[i]);
                    list.add(nums[left]);
                    list.add(nums[right]);
                    res.add(list);

            // 去重
                    --right;
                    while(right>left&&nums[right]==nums[right+1]){
                        --right;
                    }
                    ++left;
                    while(right>left&&nums[left]==nums[left-1]){
                        ++left;
                    }
                }else if(nums[left]+nums[right]+nums[i]>0){
                    --right;
                }else{
                    ++left;
                }
            }
        }
        return res;
    }
}