0

I am trying to improve my javascript skills, I am stuck on a problem I am working through.

// Given an integer array, output all pairs that sum up to a specific value p.

var sum = function(array, value){
    var solutionArray = [];
    for (i = 0; i < array.length; i++){
      for(j = 0; j < array.length; j++){
          if(array[i] + array[j] === value){                  
              solutionArray.push([array[i], array[j]]);
          }
        }
    }
    return solutionArray;    
};

This 'works' but I can't filter for duplicates. I would like to only have one match instead of displaying multiple. If anyone has any suggestions I would appreciate it.

I have been experimenting adding an && case to my if statement. I haven't found the logic to make that work.

I have also been experimenting filtering through my array before I return it and after it completed both loops.

Here is a repl.it I made of the problem: http://repl.it/QIk/1

HelloWorld
  • 10,529
  • 10
  • 31
  • 50
  • possible duplicate of [Unique values in an array](http://stackoverflow.com/questions/1960473/unique-values-in-an-array) – bjb568 Mar 19 '14 at 03:48

3 Answers3

2

This will be more efficinet than the O(N^2) checks.

var seen = {};
solutionArray = solutionArray.reduce(function(result, currentItem) {
    if (currentItem.join("") in seen === false) {
        result.push(currentItem);
        seen[currentItem.join("")] = false;
    }
    return result;
}, []);
return solutionArray;

Check the updated repl.it link

thefourtheye
  • 233,700
  • 52
  • 457
  • 497
1

This solves the problem without having to iterate over the previous results, and also takes care about removing duplicates.

The steps are:

  1. build the pair (a,b) where a+b==value
  2. sort that pair, ie: pairs (1,2) and (2,1) will become (1,2)
  3. build a string joining by any character (ie: ',') the sorted pair, ie: pair (1,2) => pairKey = '1-2';
  4. check if the pairKey exists on an object (alreadyExists) and if not add it to the results and mark it as alreadyExist

This is the code:

var sum = function(array, value){
  var alreadyExists = {};
  var solutionArray = [];
  for (i = 0; i < array.length; i++){
    for(j = i+1; j < array.length; j++){
      if(array[i] + array[j] === value) {                  

        var pair = [array[i], array[j]];
        var pairKey = pair.sort().join(",");

        if ( ! alreadyExists.hasOwnProperty(pairKey) ) {
          solutionArray.push(pair);
          alreadyExists[pairKey] = 1;
        }

      }
    }
  }
  return solutionArray;    
};

Play with it at http://repl.it/QIk/3

Note: Since the original post I've modified the double loop from:

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

to:

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

Because that had 2 problems:

  1. It checked each element with itself giving false pairs as results (ie: [5,0] provided pairs like [5,5])
  2. It goes over previous analyzed combinations, ie: [1,2,3] ==> 1+2 and 2+1 when there were already checked, therefore we can reduce the number of iterations.
mgo1977
  • 81
  • 3
0

This should do it:

var sum = function(array, value){
  var solutionArray = [];
  for (i = 0; i < array.length; i++){
    for(j = 0; j < array.length; j++){
      if(array[i] + array[j] === value) {                  
        var alreadyExists = solutionArray.some(function (it) {
          return it[0] === array[i] && it[1] === array[j];
        });
        if ( ! alreadyExists) {
          solutionArray.push([array[i], array[j]]);
        }
      }
    }
  }
  return solutionArray;    
};

To also exclude reversed pairs, change:

return it[0] === array[i] && it[1] === array[j];

to

return (
  (it[0] === array[i] && it[1] === array[j]) ||
  (it[1] === array[i] && it[0] === array[j])
);
sabof
  • 8,062
  • 4
  • 28
  • 52