HomeLeetcode15. 3Sum - Leetcode Solutions

15. 3Sum – Leetcode Solutions

Description:

Given an integer array nums, return all the triplets [nums[i], nums[j], nums[k]] such that i != ji != k, and j != k, and nums[i] + nums[j] + nums[k] == 0.

Notice that the solution set must not contain duplicate triplets.

Examples:

Example 1:

Input: nums = [-1,0,1,2,-1,-4]
Output: [[-1,-1,2],[-1,0,1]]
Explanation: 
nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0.
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0.
nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0.
The distinct triplets are [-1,0,1] and [-1,-1,2].
Notice that the order of the output and the order of the triplets does not matter.

Example 2:

Input: nums = [0,1,1]
Output: []
Explanation: The only possible triplet does not sum up to 0.

Example 3:

Input: nums = [0,0,0]
Output: [[0,0,0]]
Explanation: The only possible triplet sums up to 0.

Solution in Python:

To solve the problem of finding all unique triplets in an array that sum up to zero, we can use a two-pointer approach after sorting the array. This approach ensures an efficient solution with O(n2) time complexity.

Python
from typing import List

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        # Sort the array
        nums.sort()
        result = []
        
        # Iterate through the array
        for i in range(len(nums) - 2):
            # Skip duplicate elements to avoid duplicate triplets
            if i > 0 and nums[i] == nums[i - 1]:
                continue
            
            # Initialize two pointers
            left, right = i + 1, len(nums) - 1
            
            while left < right:
                total = nums[i] + nums[left] + nums[right]
                
                if total == 0:
                    # Found a triplet
                    result.append([nums[i], nums[left], nums[right]])
                    
                    # Skip duplicates for left pointer
                    while left < right and nums[left] == nums[left + 1]:
                        left += 1
                    # Skip duplicates for right pointer
                    while left < right and nums[right] == nums[right - 1]:
                        right -= 1
                    
                    # Move both pointers
                    left += 1
                    right -= 1
                elif total < 0:
                    # Move left pointer to the right to increase the sum
                    left += 1
                else:
                    # Move right pointer to the left to decrease the sum
                    right -= 1
        
        return result

# Example usage:
sol = Solution()
print(sol.threeSum([-1, 0, 1, 2, -1, -4])) # Output: [[-1, -1, 2], [-1, 0, 1]]
print(sol.threeSum([0, 1, 1])) # Output: []
print(sol.threeSum([0, 0, 0])) # Output: [[0, 0, 0]]

Explanation:

  1. Sorting:
    • The array is sorted to make it easier to avoid duplicates and to use the two-pointer technique efficiently.
  2. Main Loop:
    • The loop iterates through the array, fixing one element nums[i] at a time.
    • If nums[i] is the same as the previous element, it is skipped to avoid duplicate triplets.
  3. Two-Pointer Technique:
    • Two pointers, left and right, are initialized. left starts right after i, and right starts at the end of the array.
    • The sum of the triplet nums[i] + nums[left] + nums[right] is calculated.
    • If the sum is zero, the triplet is added to the result list.
    • If the sum is less than zero, the left pointer is moved to the right to increase the sum.
    • If the sum is greater than zero, the right pointer is moved to the left to decrease the sum.
  4. Avoiding Duplicates:
    • After finding a valid triplet, the left and right pointers are moved to skip over any duplicate values to ensure that each triplet is unique.

This solution is efficient and ensures that all unique triplets are found with a time complexity of O(n2) making it suitable for the given constraints.

Solution in Javascript:

JavaScript
/**
 * @param {number[]} nums
 * @return {number[][]}
 */
var threeSum = function(nums) {
    // Sort the array
    nums.sort((a, b) => a - b);
    let result = [];
    
    // Iterate through the array
    for (let i = 0; i < nums.length - 2; i++) {
        // Skip duplicate elements to avoid duplicate triplets
        if (i > 0 && nums[i] === nums[i - 1]) continue;
        
        // Initialize two pointers
        let left = i + 1;
        let right = nums.length - 1;
        
        while (left < right) {
            let total = nums[i] + nums[left] + nums[right];
            
            if (total === 0) {
                // Found a triplet
                result.push([nums[i], nums[left], nums[right]]);
                
                // Skip duplicates for left pointer
                while (left < right && nums[left] === nums[left + 1]) left++;
                // Skip duplicates for right pointer
                while (left < right && nums[right] === nums[right - 1]) right--;
                
                // Move both pointers
                left++;
                right--;
            } else if (total < 0) {
                // Move left pointer to the right to increase the sum
                left++;
            } else {
                // Move right pointer to the left to decrease the sum
                right--;
            }
        }
    }
    
    return result;
};

// Example usage:
console.log(threeSum([-1, 0, 1, 2, -1, -4])); // Output: [[-1, -1, 2], [-1, 0, 1]]
console.log(threeSum([0, 1, 1])); // Output: []
console.log(threeSum([0, 0, 0])); // Output: [[0, 0, 0]]

Solution in Java:

Java
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        // Sort the array
        Arrays.sort(nums);
        List<List<Integer>> result = new ArrayList<>();
        
        // Iterate through the array
        for (int i = 0; i < nums.length - 2; i++) {
            // Skip duplicate elements to avoid duplicate triplets
            if (i > 0 && nums[i] == nums[i - 1]) continue;
            
            // Initialize two pointers
            int left = i + 1;
            int right = nums.length - 1;
            
            while (left < right) {
                int total = nums[i] + nums[left] + nums[right];
                
                if (total == 0) {
                    // Found a triplet
                    result.add(Arrays.asList(nums[i], nums[left], nums[right]));
                    
                    // Skip duplicates for left pointer
                    while (left < right && nums[left] == nums[left + 1]) left++;
                    // Skip duplicates for right pointer
                    while (left < right && nums[right] == nums[right - 1]) right--;
                    
                    // Move both pointers
                    left++;
                    right--;
                } else if (total < 0) {
                    // Move left pointer to the right to increase the sum
                    left++;
                } else {
                    // Move right pointer to the left to decrease the sum
                    right--;
                }
            }
        }
        
        return result;
    }

    // Example usage
    public static void main(String[] args) {
        Solution sol = new Solution();
        List<List<Integer>> result = sol.threeSum(new int[]{-1, 0, 1, 2, -1, -4});
        for (List<Integer> triplet : result) {
            System.out.println(triplet);
        }
    }
}

Solution in C#:

C#
using System;
using System.Collections.Generic;

public class Solution {
    public IList<IList<int>> ThreeSum(int[] nums) {
        // Sort the array
        Array.Sort(nums);
        IList<IList<int>> result = new List<IList<int>>();
        
        // Iterate through the array
        for (int i = 0; i < nums.Length - 2; i++) {
            // Skip duplicate elements to avoid duplicate triplets
            if (i > 0 && nums[i] == nums[i - 1]) continue;
            
            // Initialize two pointers
            int left = i + 1;
            int right = nums.Length - 1;
            
            while (left < right) {
                int total = nums[i] + nums[left] + nums[right];
                
                if (total == 0) {
                    // Found a triplet
                    result.Add(new List<int> { nums[i], nums[left], nums[right] });
                    
                    // Skip duplicates for left pointer
                    while (left < right && nums[left] == nums[left + 1]) left++;
                    // Skip duplicates for right pointer
                    while (left < right && nums[right] == nums[right - 1]) right--;
                    
                    // Move both pointers
                    left++;
                    right--;
                } else if (total < 0) {
                    // Move left pointer to the right to increase the sum
                    left++;
                } else {
                    // Move right pointer to the left to decrease the sum
                    right--;
                }
            }
        }
        
        return result;
    }

}

Subscribe
Notify of

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments

Popular