15. 3Sum

15. 3Sum

Leetcode Blind 75

22th June 2022 ~ Dion Pinto

Description

Given an integer array nums, return all the triplets [nums[i], nums[j], nums[k]] such that i != j, i != k, and j != k, and nums[i] + nums[j] + nums[k] == 0. Notice that the solution set must not contain duplicate triplets. (Problem)

Explanation

I believe that 3Sum becomes rather messy because of the handling of duplicates. We can see this with the following brute force approach (without handling of duplicates).


				
    class Solution:
        def threeSum(self, nums: List[int]) -> List[List[int]]:
            sol=[]
            for i in range(len(nums)-2):
                for j in range(i+1,len(nums)-1):
                    if(i!=j):
                        for k in range(j+1,len(nums)):
                            if(j!=k):
                                if(nums[i]+nums[j]+nums[k]==0):
                                    sol.append([nums[i],nums[j],nums[k]])
            return sol

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

    OUTPUT: [[-1,0,1],[-1,2,-1],[0,1,-1]]
							
			

In the above output we can notice [-1,0,1] is repeated twice with the order being different. We can solve the order issue by sorting the input array.


				
        ...
        def threeSum(self, nums: List[int]) -> List[List[int]]:
            sol=[]
            nums.sort()
            for i in range(len(nums)-2):
        ...

        OUTPUT: [[-1,-1,2],[-1,0,1],[-1,0,1]]
							
			

Cool now we atleast get the duplicates in order.Now we can focus on eliminating the duplicates. We can notice that if we just skip the repeating values after sorting we can eliminate the duplicates.

We can use the following code to do so.


				
        ...
        nums.sort()
        sol=[]
        for i in range(len(nums)-2):
            if(i>0 and nums[i]==nums[i-1]):
                continue
            for j in range(i+1,len(nums)-1):
        ...

        OUTPUT: [[-1,-1,2],[-1,0,1]]
							
			

Now finally, we can move onto a more optimized soluton. As we have seen in (two Sum 2). Utilizing a 2 pointer approach to find the j -> nums[l] and k -> nums[r] values. ending with a another check to ensure no duplicates occur.


				
        ...
         else:
            sol.append([nums[i],nums[l],nums[r]])
                l+=1
            while((l<r) and nums[l]==nums[l-1]):
                l+=1
        ...
							
			

Code (Python)


				
    class Solution:
        def threeSum(self, nums: List[int]) -> List[List[int]]:
            sol=[]
            nums.sort()
            for i in range(len(nums)):
                if(i>0 and nums[i]==nums[i-1]):
                    continue
                
                l,r=i+1,len(nums)-1
                while(l<r):
                    
                    threesum=nums[i]+nums[l]+nums[r]
                    if(threesum>0):
                        r-=1
                    elif(threesum<0):
                        l+=1
                    else:
                        sol.append([nums[i],nums[l],nums[r]])
                        l+=1
                        while((l<r) and nums[l]==nums[l-1]):
                                l+=1
            return sol
							
			

Time Complexity => o(n2)

Space Complexity => o(1)

Back