3

This was an Amazon interview question I had an my answer was

function intersection ( A , B ) 
{
    var C = [];
    for ( var a in A ) if ( B.indexOf(a) != -1 ) C.push(a);
    return C;
}

and he asked what the order of complexity was and I said, and I quote exactly,

O(m * n) where m=A.length and n=B.length

and he was saying there's a better way to do it and I was like WTF??????? He was saying use A and B as Objects and I was like

"But you said these were arrays That was your question!!!!"

Can someone help me out here?

6
  • I'm not sure how 'use as objects' helps, but if you make a lookup-table (dictionary) from B before you start, then you can do it in O(n). Commented Sep 25, 2015 at 16:30
  • 3
    If you're in another JavaScript interview, don't use for ... in to loop through arrays. Commented Sep 25, 2015 at 16:31
  • 1
    btw there are lots of questions on SO for this question, eg: stackoverflow.com/questions/1885557/… Commented Sep 25, 2015 at 16:32
  • 1
    @JonTrauntvein no it would be O(n+m) which is really just O(n) Commented Sep 25, 2015 at 16:33
  • 2
    If A and B are arrays, this won't do what it pretends to. In for (var a in A) { ... } the variable a will hold the indices. Commented Sep 25, 2015 at 16:33

1 Answer 1

6

If you know that the array values are strings or numbers, you can create an object that's got the values as property names and truthy values for each. Then you can use simple object lookup in a pass through the second array.

Something like:

function intersection ( A , B ) 
{
    var m = A.reduce(function(m, v) { m[v] = 1; return m; }, {});
    return B.filter(function(v) { return m[v]; });
}

edit — to remove duplicates from the result, another .reduce() pass could be used:

function intersection ( A , B ) 
{
    var m = A.reduce(function(m, v) { m[v] = 1; return m; }, {});
    return B.reduce(function(rv, v) {
      if (!rv.m[v]) {
        rv.m[v] = 1;
        rv.l.push(v);
      }
      return rv;
    }, {m:{}, l:[]}).l;
}
Sign up to request clarification or add additional context in comments.

7 Comments

and If the values are objects but reference equality is all right, you can use a Set()
@Touffy yes good point, in fact you could use a Set anyway. I haven't fully acclimated to ES2015 yet :)
Note that in practice, if A.length or B.length is small, you might actually get better performance with an array lookup: jsperf.com/key-or-array-search/2 (from stackoverflow.com/questions/26353417/…)
@nrabinowitz yes, somehow modern browsers do .indexOf() incredibly quickly.
Or they have more overhead than expected for object key lookup.
|