Text: Fill in the missing variables labeled with x = 1...16
Selection
Suppose that you have two arrays of integers, A and B. They are both arranged in ascending order. A has length n and B has length m, and n+m > 0. We would like an O(log n + log m) divide and conquer algorithm that can find the element that would be stored at index k if the arrays were merged into a single ordered array.
For example, suppose A and B are:
A = [2, 5, 7, 22]
B = [7, 8, 9, 14]
The element that would be stored at index 5 of the merged array M = [2, 5, 7, 7, 8, 9, 14, 22] is 9. Unfortunately, actually merging A and B would require (n+m) time in the worst case, which is too long.
Here is the skeleton of a solution. In 16 places, I have removed an expression and replaced it with x, for x = 1..16.
// A and B are each sorted into ascending order, and 0 <= k < |A|+|B|
// Returns the element that would be stored at index k if A and B were
// combined into a single array that was sorted into ascending order.
select(A, B, k)
return select(A, 0, |A|-1, B, 0, |B|-1, k)
select(A, loA, hiA, B, loB, hiB, k)
// A[loA..hiA] is empty if(hiA < loA)
return B[k-loA]
// B[loB..hiB] is empty if(hiB < loB)
return A[k-loB]
// Get the midpoints of A[loA..hiA] and B[loB..hiB]
i = (loA + hiA)/2
j = (loB + hiB)/2
// Figure out which one of four cases apply
if(A[i] > B[j])
if(k <= i+j)
return select(A, loA, i-1, B, loB, hiB, k);
else
return select(A, i, hiA, B, j+1, hiB, k);
else if(k <= i+j)
return select(A, loA, hiA, B, loB, j-1, k);
else
return select(A, i+1, hiA, B, loB, hiB, k);