15. 3Sum

Description:

Given an array S of n integers, are there elements a, b, c in S 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.

For example, given array S = [-1, 0, 1, 2, -1, -4],

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

Solutions:

Approach 1: failed with time complexity of O(n^3)

This approach is simple and time cost. It uses 3 loops (i in first loop, j in second loop and k in third loop) to scan the arrays and finds all the combination of 3 elements in the array. If the sum of any of the combinations is zero, the triplets can be added into the list. However, the description requires that the solution cannot contain duplicate triplets. So we have to check if all the triplets are unique. This is another time-costing process.

If we first sort the array and use some tricks, we may well handle the duplicates. However, what I think of is that every time we check in every loop if num[i] == num[i-1], if so, we just let i++. But this doesn't work because, for example, we would get i to 3 if the array is [0, 0, 0, 0].

But we know that the first three elements can form a list that satisfy the condition. What if we just do not check first time in the loop? For example, we would change the if clause to if (i > 0 && i < len-2 && num[i] == num[i-1]) i++, where i would not increase to 3 at the first time. In the same way we change the if clause in the second loop to if (j > 1 && j < len-1 && num[j] == num[j-1]) j++ and in the third loop to if (k > 2 && k < len && num[k] == num[k-1]) k++. However, this doesn't work, either. This is because, for example, if the array is

[-4, -1, -1, 0, 1, 2]

and when i = 1 and j = 2, we know that if k = 5, nums[1] + nums[2] + nums[5] = -1 -1 + 2 = 0. But the algorithm would say: since j = 2 and nums[2] == nums[1], so j++. This would lead j= 3. So the algorithm fails. I haven't think of other good solutions to this issue. So I looked at the discuss and the approach 2 is as followings.

Approach 2: Use 3 pointers with time complexity of O(n^2)

In this approach, we use 3 pointers where the first pointer i just goes from the start to the end and divides the array into the left part and the right part, while the other two named j and k sweep from the right-part array from both of the ends until they meet or cross, which means j = i+1 and k = nums.length-1 at first.
To deal with the duplicate situation, we have 2 steps to go:

  • First, we check if nums[i] == nums[i-1], which means we check if the present element is equal to the previous one, if so, we let i++. So in this way, we can guarantee that i always points to a new elements.
  • Second, since we let j = i+1 and k = nums.length-1, we always check if nums[j] == nums[j+1] and nums[k] == nums[k-1], if so, we let j++ and k--. So please pay attention that this is different from i case. We check if the present element is equal to the future element but not the previous element.
    The codes are as followings:
class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        Arrays.sort(nums);
        List<List<Integer>> list = new ArrayList<>();
        for (int i = 0; i < nums.length-2; i++) {
            if (nums[i] > 0) break;
            // if there is several same numbers in the arary, skip to a different one
            if (i > 0 && nums[i] == nums[i-1]) continue;
            int lo = i+1, hi = nums.length-1, target = -nums[i];
            while (lo < hi) {
                if (nums[lo] + nums[hi]  == target) {
                    list.add(Arrays.asList(nums[i], nums[lo], nums[hi]));
                    while (lo < hi && nums[lo] == nums[lo+1]) lo++;
                    while (lo < hi && nums[hi] == nums[hi-1]) hi--;
                    lo++;
                    hi--;
                } else if (nums[lo] + nums[hi] < target) {
                    lo++;
                } else {
                    hi--;
                }
            }
            
        }
        return list;
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 背景 一年多以前我在知乎上答了有关LeetCode的问题, 分享了一些自己做题目的经验。 张土汪:刷leetcod...
    土汪阅读 12,775评论 0 33
  • **2014真题Directions:Read the following text. Choose the be...
    又是夜半惊坐起阅读 9,932评论 0 23
  • 知识贡献收益渠道很多啊:专头、知识星球(原小密圈)、小鹅通、三分钟、百度问咖、社会斜杠职业协作有:有轻功又高又冷又...
    咸叔说阅读 257评论 0 1
  • 首先,我是在单亲家庭长大的,但父母都没有再婚,我还是感觉受到了伤害,我不是轻易哭的女孩,如果我哭就会痛哭一场。...
    安海希阅读 259评论 0 0
  • 宝宝脸上长湿疹了之后,一定要给孩子及时采取合理的治理方法,防止宝宝湿疹的进一步扩大,从而不让宝宝进一步受到湿疹的影...
    贝安宁beianning阅读 361评论 0 0