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

1

3 Answers 3

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

Sign up to request clarification or add additional context in comments.

Comments

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.

Comments

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.