6

I have the following question (this is not school -- just code site practice questions) and I can't see what my solution is missing.

A non-empty array A consisting of N integers is given. The array contains an odd number of elements, and each element of the array can be paired with another element that has the same value, except for one element that is left unpaired.

Assume that:

  • *N is an odd integer within the range [1..1,000,000];
  • *each element of array A is an integer within the range [1..1,000,000,000];
  • *all but one of the values in A occur an even number of times.

EX: A = [9,3,9,3,9,7,9] Result: 7

The official solution is using the bitwise XOR operator :

function solution(A) {
    
    var agg = 0;
    
    for(var i=0; i<A.length; i++) {
        agg ^= A[i];
    }
    
    return agg;
}

My first instinct was to keep track of the occurrences of each value in a Map lookup table and returning the key whose only value appeared once.

function solution(A) {

    if (A.length < 1) {return 0}
    let map = new Map();
    let res = A[0]
    for (var x = 0; x < A.length; x++) {
        if (map.has(A[x])) {
            map.set(A[x], map.get(A[x]) + 1)
        } else {
            map.set(A[x], 1)
        }
    }
    for ([key,value] of map.entries()) {
        if (value===1) {
            res = key
        } 
    }

    return res;
}

I feel like I handled any edge cases but I'm still failing some tests and it's coming back with a 66% correct by the automated scorer.

Henke
  • 4,445
  • 3
  • 31
  • 44
Jason Boyas
  • 113
  • 1
  • 5

5 Answers5

11

You could use a Set and check if deletion deletes an item or not. If not, then add the value to the set.

function check(array) {
    var s = new Set;
    
    array.forEach(v => s.delete(v) || s.add(v));
    
    return s.values().next().value;
}

console.log(check([9, 3, 9, 7, 3, 9, 9])); // 7
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
4

You're not accounting for cases like this:

[ 1, 1, 2, 2, 2 ] => the last 2 is left unpaired

So your condition should be if ( value % 2 ) instead of if ( value === 1 ).

I think also there is not much benefit to using a Map rather than just a plain object.

We Are All Monica
  • 13,000
  • 8
  • 46
  • 72
1

The official solution works due to the properties of the bitwise XOR (^), namely the fact that a ^ a == 0, a ^ 0 == a, and that the operation is commutative and associative. This means that any two equal elements in the array will cancel each other out to become zero, so all numbers appearing an even amount of times will be removed and only the number with an odd frequency will remain. The solution can be simplified using Array#reduce.

function findOdd(arr) {
    return arr.reduce((a,c)=>a ^ c, 0);
}
Unmitigated
  • 76,500
  • 11
  • 62
  • 80
0

You need not to make a count of each and traverse again, if you are sure that there will be exactly one number which will occur odd number of times. you can sum the array and do + when odd entry and - when even entry (to dismiss it back) and in the hash (map or object) you can just toggle for subsequent entry of each number.

Here is an example:

let inputArray1 = [10,20,30,10,50,20,20,70,20,70,50, 30,50], //50 -> 3 times
    inputArray2 = [10,20,30,20,10], //30 -> 1 time
    inputArray3 = [7,7,7,7,3,2,7,2,3,5,7]; //5 -> 1 time

let getOddOccuence = arr => {
  let hash = {};
  return arr.reduce((sum, n) => sum + ((hash[n] = !hash[n]) ? n : -n), 0);
}

console.log('Input Array 1: ', getOddOccuence(inputArray1));
console.log('Input Array 2: ', getOddOccuence(inputArray2));
console.log('Input Array 3: ', getOddOccuence(inputArray3));

In case the input contains multiple or no numbers having odd number of occurance (if you are not sure there) then you have already the hash (and you can ignore performing sum) and return the keys of hash (where value is true (and not checking with %2 and then consider as truthy or false in case of you have count))

Koushik Chatterjee
  • 4,106
  • 3
  • 18
  • 32
0

function solution(A) {
    let result = 0;
  
    for (let element of A) {
        // Apply Bitwise XOR to the current and next element
        result ^= element;
    }

    return result;
}

const unpaired = solution([9, 3, 9, 3, 9, 7, 9]);

console.log(unpaired);

Source: https://gist.github.com/k0ff33/3eb60cfb976dee0a0a969fc9f84ae145

gcfabri
  • 564
  • 2
  • 7
  • 28