There are all N elements in an array. When you are asked to get the kth greatest number, how will you do? There are several approaches:
First, you can sort the array, and then the index of the kth greatest number is k. You can apply Mergesort, Heapsort and Quicksort. The upper bound of Mergesort is O ( n lg n ) O(n\lg n) O(nlgn). If you apply Heapsort, the time complexity is. O ( k lg n ) O(k\lg n) O(klgn). And if Quicksort, the expected time is O ( n lg n ) O(n\lg n) O(nlgn).
Second, we can apply an algorithm modeled after Quicksort —— we partition the input array in a
Recursive way. But unlike Quicksort, in this way, we only deal with only one side of the partition. The code of the algorithm is as follows.
int Partition(int *A, int p, int r)
{
int i = p - 1, q = p;
for (; q < r; q++)
{
if (A[q] <= A[r])
{
i++;
int temp;
temp = A[q]; A[q] = A[i]; A[i] = temp;
}
}
i++;
int temp;
temp = A[r]; A[r] = A[i]; A[i] = temp;
return i;
}
int RandomizedPartition(int *A, int p, int r)
{
int i = rand() % (r - p + 1) + p;
int temp;
temp = A[i]; A[i] = A[r]; A[r] = temp;
return Partition(A, p, r);
}
int RandomizedSelect(int *A, int p, int r, int i)
{
int q = RandomizedPartition(A, p, r);
if (i == q) {
return A[i];
}
else if (i < q)
return RandomizedSelect(A, p, q-1, i);
else
return RandomizedSelect(A, q+1, r, i);
}
Just like Quicksort, we should deal with the best case and the worst case respectively. In the worst case, T ( n ) = T ( n − 1 ) + O ( n ) T(n) = T(n-1) + O(n) T(n)=T(n−1)+O(n) , while in the best case, T ( n ) = T ( n 2 ) + O ( n ) T(n) = T(\frac{n}{2}) + O(n) T(n)=T(2n)+O(n). However, we can work out the expected time complexity as Quicksort —— O ( n ) O(n) O(n). The calculation is very complex, so I haven’t really understand it. But I have an intuitive understanding over it as Quicksort.
But we can also use a selection algorithm whose running time is O ( n ) O(n) O(n) in the worst case. The algorithm is interpreted as follows.
STEP 1: Divide the array into several parts, every of which has 5 elements;
STEP 2: We should find the median of the medians. In another word, find the median of every part, and then find the median of these medians in the way of calling the selection function;
STEP 3: With the median as a pivot, call the function Partition;
STEP 4: Call the selection function in a recursive way.
STEP 1: T ( n ) = O ( 1 ) T(n) = O(1) T(n)=O(1);
STEP 2: T ( n ) = n 5 O ( 1 ) + T ( n 5 ) T(n) = \frac{n}{5}O(1) + T(\frac{n}{5}) T(n)=5nO(1)+T(5n);
STEP 3: T ( n ) = O ( n ) T(n) = O(n) T(n)=O(n);
STEP 4: The number of the elements which is greater than the pivot in the array is more than 3 n 10 \frac{3n}{10} 103n, the smaller one is more than 3 n 10 \frac{3n}{10} 103n also. Therefore, the number of the elements in one side of the array is less than 7 10 \frac{7}{10} 107, T ( n ) = T ( 7 n 10 ) T(n) = T(\frac{7n}{10}) T(n)=T(107n).
T ( n ) = O ( 1 ) + n 5 O ( 1 ) + T ( n 5 ) + O ( n ) + T ( 7 n 10 ) T(n) = O(1) + \frac{n}{5}O(1) + T(\frac{n}{5}) + O(n) + T(\frac{7n}{10}) T(n)=O(1)+5nO(1)+T(5n)+O(n)+T(107n).
We can use the substitution method to work out that T ( n ) = O ( n ) T(n) = O(n) T(n)=O(n).
To get the complete code please visit my repositories: github.com.
Reference:
- Introduction to algorithm
- https://www.ics.uci.edu/~eppstein/161/960130.html