GuilinDev

Lc0015

05 August 2008

15 - 3Sum

原题概述

Given an array ‘nums’ of n integers, are there elements a, b, c in ‘nums’ such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.

Note:

The solution set must not contain duplicate triplets.

Example:

1
2
3
4
5
6
7
Given array nums = [-1, 0, 1, 2, -1, -4],

A solution set is:
[
  [-1, 0, 1],
  [-1, -1, 2]
]

题意和分析

这个题的意思是在Array中找到三个数加起来为0, 用1-2Sum的双指针的方法来解,先对Array排序,然后拿出第一个index从左到右循环,第二第三个index分别向右向左移动来确定triplet;找到triplet后还需要考虑去除重复triplets的问题,这里直接用了hashset来判断triplet-ArrayList<Integer>是否相同,也可以存到map里面,判断一下如果有相同的key就不存进去。

时间复杂度: O(nlogn) + O(n^2) = O(n^2);空间复杂度O(n)。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> results = new ArrayList<>();
        if (nums == null || nums.length < 3) {
            return results;
        }
        int len = nums.length;
        HashSet<List<Integer>> noDup = new HashSet<>();
        Arrays.sort(nums);
        List<Integer> oneResult = new ArrayList<>();
        for (int first = 0; first < len - 2; first++) {
            int second = first + 1, third = len - 1;
            while (second < third) {
                int sum = nums[first] + nums[second] + nums[third];
                if (sum == 0) {
                    oneResult.add(nums[first]);
                    oneResult.add(nums[second]);
                    oneResult.add(nums[third]);
                    if (noDup.add(oneResult)) {
                        results.add(oneResult);
                    }
                    // 不管是否重复,都要重新设置
                    oneResult = new ArrayList<>();
                    second++;
                    third--;
                } else if (sum > 0) {
                    third--;
                } else {
                    second++;
                }
            }
        }
        return results;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        ArrayList<List<Integer>> result = new ArrayList<List<Integer>>(); //保持最终结果
        HashSet<ArrayList<Integer>> noDuplicateTriplets = new HashSet<ArrayList<Integer>>();//保持中间找到的triplet不要是重复的
        
        if (nums == null || nums.length < 3) {
            return result;
        }
        
        Arrays.sort(nums);
        
        for (int first = 0; first <= nums.length - 3; first++) {
            int second = first + 1, third = nums.length - 1;
            
            //接下来需要确定第二个指针second和第三个指针third是否找到合适的triplet或者相遇
            while (second < third) {
                int sum = nums[first] + nums[second] + nums[third];
                if (sum < 0) {
                    second++;
                } else if (sum > 0) {
                    third--;
                } else { //找到了一个triplet
                    ArrayList<Integer> oneTriplet = new ArrayList<Integer>();
                    oneTriplet.add(nums[first]);
                    oneTriplet.add(nums[second]);
                    oneTriplet.add(nums[third]);
                    
                    if (!noDuplicateTriplets.contains(oneTriplet)) {//因为是排好序的,所以找出来的triplet直接跟之前的所有triplets比较一下看看是否重复
                        //下面这句话也可以作为判断条件
                        noDuplicateTriplets.add(oneTriplet);//没有重复就加到hashset里面为了接下来比较下一个可能的triplet比较
                        result.add(oneTriplet);//没有重复同时也加到结果里面
                    }
                    
                    //注意这里second和third是同时移动,因为排过序了后找到的是已经等于target了,所以只移动一个index的话是不会再找到非重复的triplet的
                    second++;
                    third--;
                }
            }
        }
        return result;
    }
}