The task:
You are given 3 sorted arrays. You should find the smallest number that is common in all 3 arrays and return it. If such a number doesn't exist, return -1
My approach:
- Use early exit: If one of the array is empty, then we know there won't be a common number in all arrays
- Create pointer that points to the first element of the corresponding array
- In the outer loop, loop through all elements of the first array. If any of the pointer over reaches the end of the array, then break the loop because we have reached the end and haven't found a common number
- In the first inner loop check the second array for the element the pointer of the first array is pointing to
- If you found it then set a flag. Otherwise remember the running index to the second pointer so we can continue at this element in the next iteration
- If the flag is set, then loop through the second inner loop. In here it's analogous to the first inner loop: Search for the current element in the 3rd array.
- If you find it, then immediately return the value. If not go to the next element until you find an element bigger than the current one
- Increment the pointer of the first array
- Do this until you reach either one of the array
My Solution:
let findLeastCommonNumber = function(a, b, c) {
if (a.length === 0 || b.length === 0 || c.length === 0) {
return -1;
}
let aPointer = 0;
let bPointer = 0;
let cPointer = 0;
while (aPointer < a.length ||
bPointer < b.length ||
cPointer < c.length) {
const aValue = a[aPointer];
let bFound = false;
for (let i = bPointer; i < b.length; i++) {
if (b[i] === aValue) {
bPointer = i;
bFound = true;
break;
}
if (b[i] > aValue) {
bPointer = i;
break;
}
}
if (bFound) {
for (let i = cPointer; i < c.length; i++) {
if (c[i] === aValue) {
return a[aPointer];
}
if (c[i] > aValue) {
cPointer = i;
break;
}
}
}
aPointer++;
}
return -1;
};
Sample solution:
let find_least_common_number = function(a, b, c) {
let i = 0;
let j = 0;
let k = 0;
while (i < a.length
&& j < b.length
&& k < c.length) {
// Finding the smallest common number
if (a[i] === b[j]
&& b[j] === c[k]) {
return a[i];
}
// Let's increment the iterator
// for the smallest value.
if (a[i] <= b[j]
&& a[i] <= c[k]) {
i++;
} else if (b[j] <= a[i]
&& b[j] <= c[k]) {
j++;
} else if (c[k] <= a[i]
&& c[k] <= b[j]) {
k++;
}
}
return -1;
};
I like the fact that the sample solution has less nesting. But the sample solution doesn't take advantage of an early exit and I think my solution is more scalable. Let's say the requirements changes, and 27 arrays more are now included. In my solution, I'd just copy the inner loops and change the pointer names only. I don't need to touch existing code. In the sample solution, however, I'd have touch every line of code that refers to one of the arrays and I would add the new arrays there. What do you think?