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) {
    List<List<Integer>> result = new ArrayList<List<Integer>>();
 
    if(nums == null || nums.length<3)
        return result;
 
    Arrays.sort(nums);
 
    for(int i=0; i<nums.length-2; i++){
        if(i==0 || nums[i] > nums[i-1]){
            int j=i+1;
            int k=nums.length-1;
 
            while(j<k){
                if(nums[i]+nums[j]+nums[k]==0){
                    List<Integer> l = new ArrayList<Integer>();
                    l.add(nums[i]);
                    l.add(nums[j]);
                    l.add(nums[k]);
                    result.add(l);
 
                    j++;
                    k--;
 
                    //handle duplicate here
                    while(j<k && nums[j]==nums[j-1])
                        j++;
                    while(j<k && nums[k]==nums[k+1])
                        k--;
 
                }else if(nums[i]+nums[j]+nums[k]<0){
                    j++;
                }else{
                    k--;
                }
            }
        }
 
    }
 
    return result;
}
Category >> Algorithms  
If you want someone to read your code, please put the code inside <pre><code> and </code></pre> tags. For example:
<pre><code> 
String foo = "bar";
</code></pre>
  • CP

    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;
    }

  • boyhou

    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);

    }

    }

    }

  • Gireesh

    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;

    }

    }

  • Chetan

    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++;
    }

  • Ankit


    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;
    }

  • AmourDeMai

    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.

  • Candis

    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);

    }

  • Omar Edgardo Lugo Sánchez

    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();
    }

  • Mohanasundaram Veeramuthu

    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;
    }

  • Logic Luo

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

  • Malay Shah

    It will give time limit exceeded in O(n^2) solution…

  • Adil qureshi

    A lot of code can be avoided by using a class Triplet {} and adding it to a set

  • ryanlr

    It looks working, but time is n^3.

  • ryanlr

    A great idea! Here is how to use hashmap to solve 2Sum problem: http://www.programcreek.com/2012/12/leetcode-solution-of-two-sum-in-java/

  • PK

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

  • Ranjit

    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);
    }
    }
    }
    }

  • Ranjit

    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);

    }

    }

    }

    }

  • Gaurav Sharma

    If first condition is true then second condition will not be evaluated

  • Kick Buttowski

    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];

    }

    }

  • Anirudh

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

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

  • Ajay

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

  • Ajay

    why are you running only num.length-2 times.

  • Yancey

    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;

    }

    }

  • H Chen

    Your solution is wrong. You did not eliminate the duplicated combinations.

  • doris717

    same complexity

  • Serj Sintsov

    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;
    }