LeetCode – 3Sum

Problem:

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:
Elements in a triplet (a,b,c) must be in non-descending order. (ie, a ≤ b ≤ c)
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)

Java Solution

This problem can be solved by using two pointers. Time complexity is O(n^2).

To avoid duplicate, we can take advantage of sorted arrays, i.e., move pointers by >1 to use same element only once.

public List<List<Integer>> threeSum(int[] nums) {
    Arrays.sort(nums);
 
    ArrayList<List<Integer>> result = new ArrayList<>();
 
    for (int i = 0; i < nums.length; i++) {
        int j = i + 1;
        int k = nums.length - 1;
 
        if (i > 0 && nums[i] == nums[i - 1]) {
            continue;
        }
 
        while (j < k) {
            if (k < nums.length - 1 && nums[k] == nums[k + 1]) {
                k--;
                continue;
            }
 
            if (nums[i] + nums[j] + nums[k] > 0) {
                k--;
            } else if (nums[i] + nums[j] + nums[k] < 0) {
                j++;
            } else {
                ArrayList<Integer> l = new ArrayList<>();
                l.add(nums[i]);
                l.add(nums[j]);
                l.add(nums[k]);
                result.add(l);
                j++;
                k--;
            }
        }
    }
 
    return result;
}

36 thoughts on “LeetCode – 3Sum”

  1. Duplicates can be removed using the sets in the cpp ! Is there anyone who can help me with the solution using the sets in cpp to remove the duplicates

  2. Great explanation. Thank you.

    This problem is explained in an easy to understand and detailed article on Code Recipe as well that explains the both brute force and efficient solution in depth. They have explained solution in Java, Golang and Python. Leaving link for others to refer: https://www.code-recipe.com/post/three-sum

  3. The above solution wont work with the following
    Input: [-2,0,0,2,2]
    Output: [[-2,0,2],[-2,0,2]]
    Expected: [[-2,0,2]]

  4. Duplicates can be handled using HashSet also.

    class Solution {
    public List<List> threeSum(int[] nums) {
    Set<List> result = new HashSet();

    if(nums == null || nums.length<3)
    return new ArrayList();

    Arrays.sort(nums);

    for(int i=0; i<nums.length-2; i++){
    int j=i+1;
    int k=nums.length-1;

    while(j<k){
    if(nums[i]+nums[j]+nums[k]==0){
    List l = new ArrayList();
    l.add(nums[i]);
    l.add(nums[j]);
    l.add(nums[k]);
    result.add(l);

    j++;
    k–;
    }else if(nums[i]+nums[j]+nums[k]<0){
    j++;
    }else{
    k–;
    }
    }
    }
    return new ArrayList(result);
    }
    }

  5. Not the best or fasted but cleaner and easier to understand

    public static List<List> threeSum(int[] nums) {
    List<List> result = new ArrayList<List>();
    if(nums == null || nums.length == 0) {
    return result;
    }

    Arrays.sort(nums);
    Map tripMap = new HashMap();
    dumpArray(nums);

    for(int i = 0; i < nums.length - 2; i++){
    int j = i + 1;
    int k = nums.length - 1;

    while ( j < k) {
    if(nums[i] + nums[j] + nums[k] == 0){
    List trip = new ArrayList(Arrays.asList(new Integer[]{nums[i], nums[j] , nums[k]}));
    String tripKey = nums[i] + "" + nums[j] + "" + nums[k];
    if(!tripMap.containsKey(tripKey)) {
    result.add(trip);
    tripMap.put(tripKey, true);
    }
    j++;
    k--;

    }else if(nums[i] + nums[j] + nums[k] < 0) {
    j++;
    } else {
    k--;
    }
    }
    }

    return result;

    }

  6. public static boolean is3SumArray(int [] arr1, int sum1){
    Arrays.sort(arr1);
    for(int i=0; i<arr1.length-2; i++)
    {
    int left = i+1;
    int right = arr1.length-1;
    while(left<right)
    {
    int result = arr1[i] + arr1[left] + arr1[right];
    if(result==sum1)
    return true;
    else if(resultsum1)
    right–;
    }
    }
    return false;
    }

  7. The method below has any error? Or it just becauses that the complexity is n^3 ,so it cannot pass the leetcode.

    public class Solution {

    public List<List> threeSum(int[] nums) {

    List<List> result = new ArrayList<List>();

    List list = new ArrayList();

    if(nums == null || nums.length == 0){

    return result;

    }

    Arrays.sort(nums);

    dfs(result, list, nums, 0, 0);

    return result;

    }

    private void dfs(List<List> result, List list, int[] nums, int cur, int sum){

    if(list.size() == 3 && sum == 0){

    result.add(new ArrayList(list));

    return;

    }

    if(list.size() > 3 || cur >= nums.length){

    return;

    }

    for(int i=cur; icur && nums[i]==nums[i-1])

    // continue;

    list.add(nums[i]);

    dfs(result, list, nums, i+1, sum+nums[i]);

    list.remove(list.size()-1);

    }

    }

    }

  8. Here’s my accepted solution.
    Reviews are welcome: https://github.com/mgireesh05/leetcode/blob/master/3sum/src/com/mgireesh/Solution.java

    import java.util.Arrays;
    import java.util.LinkedList;
    import java.util.List;

    public class Solution {

    public List<List> threeSum(int[] nums) {

    List<List> answer = new LinkedList<List>();

    if (nums.length < 3) {

    return answer;

    }

    Arrays.sort(nums);

    int find = 0;

    int prev_i = nums[0] - 1;

    for (int i = 0; i < nums.length - 2; i++) {

    if ((prev_i != nums[0] - 1) && (nums[i] == prev_i)) {

    continue;

    }

    prev_i = nums[i];

    int prev_j = nums[0] - 1;

    for (int j = i + 1; j j; k--) {

    if ((prev_k != nums[0] - 1) && (find == prev_k)) {

    continue;

    }

    if (nums[k] == find) {

    List solSet = new LinkedList();

    solSet.add(nums[i]);

    solSet.add(nums[j]);

    solSet.add(nums[k]);

    answer.add(solSet);

    prev_k = find;

    } else if (find > nums[k]) {

    break;

    }

    }

    }

    }

    return answer;

    }

    }

  9. This solution still giving duplicate triplets. Following changes would make this solution complete I guess to avoid duplicates.

    in case2, also add while loop for start++, same as in case 1

    in case 3, also add while loop for end–, same as in case 1.

    and finally at the end, inside for loop, add following while loop for avoiding duplicate negate values.


    while(i < a.length-1 && a[i+1] == -negate) {
    i++;
    }


  10. private static ArrayList<ArrayList> threeSum(int []S, int target)
    {
    ArrayList<ArrayList> list = new ArrayList<ArrayList>();
    Arrays.sort(S);
    for(int i=0;i<S.length;i++)
    {
    for(int j=i+1;j<S.length;j++)
    {
    for(int k=j+1;k<S.length;k++)
    {
    if((S[i]+S[j]+S[k]) == target)
    {
    ArrayList result = new ArrayList();
    result.add(S[i]);
    result.add(S[j]);
    result.add(S[k]);
    list.add(result);
    }
    }
    }
    }
    return list;
    }

  11. The better solution may have a duplicate result. If input is [0, 0, 0, 0], output will be [[0,0,0], [0,0,0]]
    To avoid it, before add to result, we should check if the temp ArrayList is already in the result.

  12. Can someone plz explain why my code is getting timed out:

    public static List<List> threeSum(int[] nums) {

    Set<List> res = new HashSet<List>();

    Arrays.sort(nums);

    for(int i=1; i=0 && ki && j<nums.length){

    int sumG = nums[k] + nums[j];

    if(sumG + nums[i] == 0){

    List list = new ArrayList();

    list.add(nums[k]);

    list.add(nums[i]);

    list.add(nums[j]);

    res.add(list);

    k–; j++;

    }

    else if(sumG + nums[i] > 0){

    k–;

    }

    else{

    j++;

    }

    }

    }

    return new ArrayList(res);

    }

  13. my solution complexity n*n

    HashMap map = new HashMap();
    int[] a = new int[] {4,5,6,7,8,-10};

    // Arrays.sort(a);
    for(int j=0;j<a.length;j++){
    int suma = -1*a[j];
    for(int i=j;i<a.length;i++){
    if(i!=j){
    int b = suma-a[i];
    if(map.containsKey(a[i])==false){
    map.put(b,a[i]);
    }else{
    Integer g = (Integer) map.get(a[i]);
    System.out.println(a[i]+"+"+g+"+"+-1*suma+"=0");
    }
    }
    }
    map.clear();
    }

  14. Hi ryanlr,

    Can you please correct my below prog that I wrote using PK’s algo & your 2Sum code using HashMap? I think I didn’t get the algorithm properly. Thank you.

    public List<List> threeSum(int[] nums) {

    List<List> result = new ArrayList<List>();
    HashSet<List> hSet = new HashSet<List>();

    if(nums.length < 3)
    return result;

    HashMap hMap = new HashMap();

    for(int i=0; i<nums.length; i++) {

    int target = -nums[i];
    if(hMap.containsKey(nums[i])) {

    List temp = new ArrayList();
    temp.add(nums[i]);
    temp.add(nums[hMap.get(nums[i])]);
    temp.add(-target);

    if(!hSet.contains(temp)) {

    hSet.add(temp);
    result.add(temp);
    }
    }
    else
    hMap.put(target – nums[i], i);
    }
    return result;
    }

  15. Hello, I have a problem. I don’t understand how avoid duplicate solutions using ”
    if (i == 0 || num[i] > num[i – 1]) {“

  16. Pseudocode :
    Iterate the array num[].
    Int target = -num[i];
    Now find twoSum for above target in array num using hashmap.

  17. int a[] = {2, 7, 11, 0, 9, 15, 7};

    for(int i = 0; i<a.length; i++){
    for(int j = i+1; j<a.length; j++){
    for(int k = j+1; k<a.length; k++){
    if(a[i]+a[j]+a[k] == 9){

    System.out.println(i + " and "+ j + " and " + k);
    }
    }
    }
    }

  18. int a[] = {2, 7, 11, 0, 9, 15, 7};

    for(int i = 0; i<a.length; i++){

    for(int j = i+1; j<a.length; j++){

    for(int k = j+1; k<a.length; k++){

    if(a[i]+a[j]+a[k] == 9){

    System.out.println(i + " and "+ j + " and " + k);

    }

    }

    }

    }

  19. my solution

    int[] array = {-1, 0, 1, 2, -1, -4, 2,-1,-1};

    int current = array[0];

    for (int i = 0; i < array.length; i++) {

    for (int j = i; j <= 2 + i && i+2 < array.length -1 ; j++) {

    if (current + array[j] + array[j + 1] == 0) {

    System.out.println(current + " " + array[j] + " " + array[j + 1]);

    }

    current = array[i];

    }

    }

  20. if (i == 0 || num[i] > num[i – 1]) {

    How does this execute for i = 0 case ? , wont you be trying to evaluate num[-1] ??

  21. okay in last iteration we have only two element left so we should come out from the loop…
    I got it !!!

  22. Make some changes to solution1 and accepted!!

    public class Solution {

    public static ArrayList<ArrayList> threeSum(int[] num) {

    //sort array

    Arrays.sort(num);

    ArrayList<ArrayList> result = new ArrayList<ArrayList>();

    for(int i=0; i 0) break;

    for(int j=i+1; j 0 && num[j] > 0) break;

    for(int k=j+1; k<num.length; k++){

    if(num[i] + num[j] + num[k] == 0) {

    ArrayList each = new ArrayList();

    each.add(num[i]);

    each.add(num[j]);

    each.add(num[k]);

    result.add(each);

    }

    while (1+k<num.length && num[k]==num[k+1]) k++;

    }

    while (j+1<num.length && num[j]==num[j+1]) j++;

    }

    while (i+1<num.length && num[i]==num[i+1]) i++;

    }

    return result;

    }

    }

  23. Seems, I have a better solutions of this problem

    boolean is3SumArray(int[] a) {
    if (a.length < 3) return false;

    Arrays.sort(a);

    for (int i = 0; i < a.length-2; i++) {
    int x = a[i];
    int yI = i+1;
    int zI = a.length-1;

    while (yI 0) zI–;
    else yI++;
    }
    }

    return false;
    }

Leave a Comment