1

Got this java solution

public List<List<Integer>> threeSum(int[] num) {
    Arrays.sort(num);
    List<List<Integer>> res = new LinkedList<>(); 
    for (int i = 0; i < num.length-2; i++) {
        if (i == 0 || (i > 0 && num[i] != num[i-1])) {
            int lo = i+1, hi = num.length-1, sum = 0 - num[i];
            while (lo < hi) {
                if (num[lo] + num[hi] == sum) {
                    res.add(Arrays.asList(num[i], num[lo], num[hi]));
                    while (lo < hi && num[lo] == num[lo+1]) lo++;
                    while (lo < hi && num[hi] == num[hi-1]) hi--;
                    lo++; hi--;
                } else if (num[lo] + num[hi] < sum) lo++;
                else hi--;
           }
        }
    }
    return res;
}

My current javascript:

var mysort = function(a, b) {
  return a - b;
}

var threeSum = function(ns) {
  // everything is sorted
  ns.sort(mysort);

  // acc
  let res = [];

  // loop all #, but we keep last 2 elements
  for (let i = 0; i < ns.length - 2; i++) {

    // 1. i === 0, rm 1st element
    // 2. same same skip
    if (i === 0 || (i > 0 && ns[i] !== ns[i - 1])) {
      //if (true) {
      // the 2nd element
      let lo = i + 1;
      // the end element
      let hi = ns.length - 1;
      // remove the 1st element
      let sum = 0 - ns[i];

      // bi search
      while (lo < hi) {

        console.log(lo, hi, ns[lo], ns[hi], sum)

        // bi search: 2nd element + end element === sum
        if ((ns[lo] + ns[hi]) === sum) {
          console.log('push');
          res.push([ns[i], ns[lo], ns[hi]]);

          // skip: lo < hi, lo skip equal
          while (lo < hi && ns[lo] === ns[lo + 1]) lo++;

          // skip: lo < hi, hi skip equal
          while (lo < hi && ns[hi] === ns[hi - 1]) hi--;

          // closer
          lo++;

          // closer
          hi--;
        } else if (ns[lo] + ns[hi] < sum)
          lo++; // lo + hi < sum, lo++
        else
          hi--; // lo + hi > sum, hi--
      }
    }

    return res;
  }
}

console.log(threeSum([-1,0,1,2,-1,-4]));

cannot pass the 1st test case:

[-1,0,1,2,-1,-4]
Prune
  • 76,765
  • 14
  • 60
  • 81
kenpeter
  • 7,404
  • 14
  • 64
  • 95

3 Answers3

1

Your code is fine, except that you misplaced the return: it should be moved out of the for loop.

So:

    return res;
  }
}

...should be:

  }
  return res;
}

As a side note, in JavaScript you don't need to safeguard against an array reference that is out of range, as that will just return undefined, which is unequal to any numerical value. So you can just do:

if (ns[i] !== ns[i - 1])

And even in Java you don't need to do this test: i > 0 &&, as that will always be true when it gets evaluated, because of shortcut evaluation. So in the Java version you can do:

if (i == 0 || num[i] != num[i-1]) {
trincot
  • 317,000
  • 35
  • 244
  • 286
0

Here is solution for your question:

function threeSum(nums){

  let len = nums.length;
  if(len < 3) return [];
  nums.sort(function(a,b){
    return a-b;
  })
  if(nums[0] > 0 || nums[0] + nums[1] + nums[2] > 0) return [];
  if(len === 3) {
    if(nums[0] + nums[1] + nums[2] === 0) return [nums];
    else return [];
  }
  //console.log(nums);
  let result = [];
  let checker = '';
  for(let i=0; i<len-2; i++){
    for(let j=i+1; j<len-1; j++){
      //since the array is sorted, we only need to start from 
      //the last index that where value was found, since 
      //nums[k] has to be a lower number.
      for(let start = len-1, k = start; k>i, k>j;) {
        let triplet = [nums[i], nums[j], nums[k]];
        let tripletString = '/' + nums[i] + ' ' + nums[j] + ' ' + nums[k] + '/';
        if(nums[i] + nums[j] === -nums[k] && !checker.includes(tripletString)){
          result.push(triplet);
          checker += tripletString; 
          start--;
          k = start;
        } else {
          k--;
        }
      }
    }
  }
  return result;
}
var output = threeSum([-1,0,1,2,-1,-4]);
console.log(output);
Rishab
  • 1,484
  • 2
  • 11
  • 22
  • 1
    This is a less efficient algorithm than what the OP was implementing. – trincot Jul 17 '19 at 13:05
  • it is interesting solution. Unfortunately, fails at [-14,-3,11,-3,12,-1,11,13,5,6,-11,-14,-6,11,-4,-15,3,-15,9,-10,13,-10,-9,-13,-12,12,-7,12,12,3,9,5,-14,-3,9,13,11,5,3,-6,-12,-1,-5,-3,-4,-2,-10,6,-10,14,3,-11,11,10,-9,7,-1,-9,4,-12,2,-2,8,3,3,-6,-7,-1,6,12,8,9,-12,10,-8,-1,-7,-3,12,-9,-12,1,-5,6,-12,-7,-2,2,-8,-13,5,9,-7,-10,-3,11,-1,-3,-13,-10,-14,11,6,-10,6,13,4,7,-13,-6,13,12,10,-15,4,13,-7,9,-8,0,4,4,-6,12,9,-2,0] – kenpeter Jul 20 '19 at 01:39
0

If you remove the type definitions the implementation will be almost identical in JavaScript

function threeSum(num) {
  // Arrays.sort(num);
  num.sort((a, b) => a-b);
  // List<List<Integer>> res = new LinkedList<>();
  const res = [];
  for (let i = 0; i < num.length-2; i++) {
      if (i == 0 || (i > 0 && num[i] != num[i-1])) {
          let lo = i+1, hi = num.length-1, sum = 0 - num[i];
          while (lo < hi) {
              if (num[lo] + num[hi] == sum) {
                  // push a new Array instead of .add List
                  res.push([num[i], num[lo], num[hi]]);
                  while (lo < hi && num[lo] == num[lo+1]) lo++;
                  while (lo < hi && num[hi] == num[hi-1]) hi--;
                  lo++; hi--;
              } else if (num[lo] + num[hi] < sum) lo++;
              else hi--;
         }
      }
  }
  return res;
}
Teneff
  • 30,564
  • 13
  • 72
  • 103