如何从一个无序数组中找到第
K
K
K大的数?
方案一:对数组排序,然后取出第
K
K
K大的数。需要
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn)的时间复杂度。
方案二:随机选择算法,对任何输入都可以达到
O
(
n
)
O(n)
O(n)的时间复杂度。
原理类似于随机快速排序
void swap(int *a, int *b)
{
int temp = *a;
*a = *b;
*b = temp;
}
int randPartion(int *arr, int left, int right)
{
int p = 1.0*rand()/RAND_MAX*(right-left)+left;
swap(&arr[p], &arr[left]);
int temp = arr[left];
while(left < right)
{
while(left<right && arr[right]>temp)
{
right--;
}
arr[left] = arr[right];
while(left<right && arr[left]<=temp)
{
left++;
}
arr[right] = arr[left];
}
arr[left] = temp;
return left;
}
//随机选择算法,递归实现
int randSelect(int *arr, int left, int right, int K)
{
if(left == right)//递归边界
{
return arr[left];
}
int p = randPartion(arr, left, right);
int M = p - left +1;//arr[p]是[left,right]中第M大
if(K == M)
{
return arr[p];
}
if(K < M)
{
return randSelect(arr,left, p-1, K);//左侧找第K大
}
else
{
return randSelect(arr, p+1, right, K-M);//右侧找K-M大
}
}