One of my friend was asked this question in an interview -
How about getting the total sum for each of the arrays and subtracting one from the other? The difference is the extra element.
eg: A = 1,2,3,4,5 B = 1,2,3,4
sum(A) = 15, sum(B) = 10; 15 - 10 = 5 which is the extra element.
Heres a solution that doesn't require hash or set, O(1) space and O(n) time. Its not the most optimal solution posted but its a good one. All you do is sum the values in list1 and sum the values list2 and find the difference.
var findExtra= function (l1, l2) {
var l1_sum = l1.reduce(function(prev, curr) {
return prev + curr;
});
var l2_sum = l2.reduce(function(prev, curr) {
return prev + curr;
});
console.log(l1_sum, l2_sum);
if (l1.length < l2.length) return l2_sum - l1_sum;
return l1_sum - l2_sum;
}
console.log(findExtra([1,2,3,4,-1], [1,2,3,4]));
If you need this to scale, then I would use one of the many Set implementations in the world. For example, Java's HashSet.
Throw all of the first array in the Set. Then, for each member of the second array, if it is contained in the Set, remove it; otherwise mark it as Unique #2. After this procedure, the last remaining member of the Set is Unique #1.
I'd probably do it this way, even on an interview, and even for simple ten-element arrays. Life is too short to spend trying to find the clever way to scale a wall when there's a perfectly good door in it.
This can be done using Xor.
First Xor all elements from both arrays. Let x and y be the extra element each array. What remains is x^y.
Now in xor, if a bit is set, it means that it is set in one of the the two numbers and not in the other one.
We can use this to find the missing indivdual numbers. So find a bit which is set in a^b. Getting Righmost bit is easy. It can be done by
n& ~(n-1)
(1110) & ~(1101) = 0010
To get each of the individual numbers, we split the numbers of both the arrays into 2 parts, numbers have the checked bit set, and which don't.We do XOR on each of the set, so that we get the values a and b. This cancels out all the repeating elements, and separates out x and y.
This can be quite confusing. Now take x=3, y = 2
x=110
y=010
x^y=100
So when we get the bit set, the number we get is bitset = 100. Third bit is set. Suppose array elements be 5,1 ( Both repeated twice)
5=101
6=001
What now, 5 has 3rd bit, so we xor it with x
we get x^5^5 = x
Similarly, 6 doesn't have 3rd bit set, so xor with y.
We get y^1^1 = y
Code
for(i=0;i<n;i++)
xor = xor^a[i]^b[i];
set_bit = xor & ~(xor-1) ;
for(i = 0; i < n; i++)
{
if(a[i] & set_bit_no)
x = x ^ a[i]; /*XOR of first set */
else
y = y ^ a[i]; /*XOR of second set*/
if(b[i] & set_bit_no)
x = x ^ b[i]; /*XOR of first set */
else
y = y ^ b[i]; /*XOR of second set*/
}
This is similar to the method posted here http://www.geeksforgeeks.org/find-two-non-repeating-elements-in-an-array-of-repeating-elements/
Here's some simple pseudocode for a solution. I'm assuming it's OK to modify the arrays and that arrays have a remove(value) method (or that you could write one trivially). It takes the 2 arrays and returns an array containg 2 values, the first is the unique value from the first array and the second is the unique value from the 2nd array.
function findUnique(a:Array, b:Array):Array {
var uniqueFromA:int;
var uniqueFromB:int;
for each(value:int in a) {
var len:int = b.length;
b.remove(value);
/* b's length didn't change, so nothing was removed, so the value doesn't
* exist in it. */
if(b.length == len) {
uniqueFromA = value;
}
}
/* Only the unique value in b still exists in b */
uniqueFromB = b[0];
return [uniqueFromA, uniqueFromB];
}
Depending on the constraints, you can solve this very quickly in linear time. If you hold an int[10], then you can assume that an element at index 1 corresponds to the number 1; the element itself holds a count of both arrays. The following pseudocode will solve the problem quickly:
let buckets = new int[10] // init all buckets to zero
for num in arr1 do buckets[num]++ // add numbers from the first array
for num in arr2 do buckets[num]++ // add from the second array
for i in 1 to 9 do // find odd man out
if buckets[i] <= 1 then return i
This is essentially a bounded hashtable. This only works if our given list of elements is constrained between 1 and 9.
Technically, you don't even need to keep a running count of each element. You could, in principle, simply loop through arr1, then iterate through arr2 until you run across an element which was not hashed from the first array.