题目描述

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

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

例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4], 满足要求的三元组集合为: [   [-1, 0, 1],   [-1, -1, 2] ]

https://leetcode-cn.com/problems/3sum/

解法1

首先对原数组nums进行排序, 用指针i指向nums的每个元素, 然后另指针j=i+1, k=|nums|-1. 指针j与k相向而行, 直到nums[i]+nums[j]+nums[k] == 0我们就找到了一个解, 此时需要继续相向而行直到k>=j. 将数组排序可以把算法的时间复杂度降低到O(n^2). 若不对数组排序, 为了寻找j, k使得nums[i]+nums[j]+nums[k] == 0, 需要使用双重循环遍历nums, 这样会使复杂度达到O(n^3).

因为题目要求“不可以包含重复的三元组”, 这就需要我们一旦找到符合条件的i, j, k. 就需要跳过nums中相同的元素(代码中被标记的部分), 以避免寻找重复的解.

例如 nums = [-1, 0, 1, 2, -1, -4], 排序后nums = [-4, -1, -1, 0, 1, 2]. 当i=1, j=2, k=5使得nums[1]+nums[2]+nums[5]==0, 寻找的其中的一个解{-1, -1, 2}; 当i=1, j=3, k=4使得nums[1]+nums[3]+num[4]找到另一个解{-1, 0, 1}. 此时, 内层循环结束, 下一次外层循环i=2, 我们又会找到重复的解{-1, 0, 1}, 而这个解在i=1使已经被找到了. 为了避免重复的解被计算, 我们需要在内层循环与外层循环找到解后, 都要跳过重复的元素, 以避免解被重复发现.

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

        for (int i = 0; i < nums.length; i++) {
            int num = nums[i];
            int j = i + 1;
            int k = nums.length - 1;

            while (j < k) {
                int l = nums[j];
                int r = nums[k];
                int sum = l + r + num;

                if (sum == 0) {
                    List<Integer> e = new ArrayList<>();
                    e.add(nums[j]);
                    e.add(nums[k]);
                    e.add(num);
                    res.add(e);

                    do
                        j++;
                    while (j < k && nums[j] == l);

                    do
                        k--;
                    while (k > j && nums[k] == r);
                } else if (sum < 0)
                    j++;
                else
                    k--;

            }

            while (i + 1 < nums.length && nums[i + 1] == num)
                i++;
        }
        return res;
    }
}

Leave a Reply

Your email address will not be published. Required fields are marked *