三数之和

135 阅读2分钟

要求:

给你一个包含 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,另外两个指针i,j分别指向剩余部分的两端

  3. i,j交替向中间移动,记录下对于每个固定指针k的前提下,满足nums[k]+nums[i]+nums[j]==0的组合

     1. nums[k]>0时,直接break跳出循环。因为后面的数再加肯定大于0
     2.当k>0且nums[k]==nums[k-1]时,跳过此元素,避免重复
     3.正常情况下按如下规则移动指针:
         1. sum<0时,i++,并跳过所有重复的nums[i];
         2. s>0时,j--,并跳过重复的nums[j];
         3. sum=0时,记录[k,i,j]至res,并执行i++和j--,并跳过所有重复的nums[i],nums[j],防止重复记录组合。
    

代码:

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> ans = new ArrayList<>();
        int len = nums.length;
        Arrays.sort(nums);
        for (int k = 0; k < len-2; k++) {
            if (nums[k] > 0) break;
            if (k > 0 && nums[k]==nums[k+1]) continue;//略过后面的操作,直接把指针k后移
            int i = k+1;
            int j = len-1;
            while (i<j) {
                int sum = nums[k]+nums[i]+nums[j];
                if (sum == 0) {
                    ArrayList<Integer> list = new ArrayList<>();
                    list.add(nums[k]);
                    list.add(nums[i]);
                    list.add(nums[j]);
                    ans.add(list);
                    while (i<j && nums[i]==nums[i+1]) i++;
                    while (i<j && nums[j]==nums[j-1]) j--;//略过重复的数字
                    i++;
                    j--;//i,j记录之后都要移动,因为下一个组合的数字必然不会再是这三个数的组合了
                }
                else if(sum<0) i++;
                else if(sum>0) j--;
            }
        }
        return ans;
    }
}