15. 3Sum

Problem

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.

Notice that the solution set must not contain duplicate triplets.

 

Example 1:

Input: nums = [-1,0,1,2,-1,-4]
Output: [[-1,-1,2],[-1,0,1]]

Example 2:

Input: nums = []
Output: []

Example 3:

Input: nums = [0]
Output: []

 

Constraints:

  • 0 <= nums.length <= 3000
  • -105 <= nums[i] <= 105

Discussion

An extended version of 1. Two Sum. Based on our result in Two Sum, we have a result of O(n) solution with two integer in the input, we can target a solution for this problem of O(n^2).

If we simply enhanced the solution based on Two Sum, we have to figure out the de-duplication step. And as the solution should be of O(n^2), we can try to sort the input array first.

And based on this, we can try to use a pointer approach to scan all the elements within each iteration.

Solution

Our solution begins with sorting the input list, then a loop iterating along the input list.

In each iteration, we will use a 2-pointer approach to scan all the pairs of elements.

As duplicate elements may appears and we want to avoid same combination, we will try to skip the first elements by skipping the element same with the previous one.

We will define the two pointers as the beginning and the end of the remaining sub list. Similarly we will update the first element if it's same as the previous one.

Then we simply evaluate the same of the three elements. If it is positive we will try to reduce it's value, then we update the last element with a smaller index, vice versa for negative value.

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        nums.sort()
        result = []

        for i in range(len(nums)):
            if i > 0 and nums[i - 1] == nums[i]:
                continue

            left, right = i + 1, len(nums) - 1

            while left < right:
                if left > i + 1 and nums[left - 1] == nums[left]:
                    left += 1
                    continue

                value = nums[i] + nums[left] + nums[right]

                if value > 0:
                    right -= 1

                elif value < 0:
                    left += 1

                else:
                    result.append([nums[i], nums[left], nums[right]])
                    left += 1
                    right -= 1

        return result

Complexity Analysis

  • Time Complexity: O(n^2), as a double loop is implemented.
  • Space Complexity: O(1), as only constant value is saved in memory.