在一个数组中找到第k小的数(线性时间选择)
在这一部分,我们讨论的题目为元素选择问题。这类题目的一般问法为:给定线性序集中n个元素和一个整数k,1 <= K <= n,要求找出这n个元素中第k小的元素,如(1,4,3,2,5)中第一小的元素就是1,第5小的元素就是5,第2小的元素就是2。
在某些特殊情况下,很容易设计出解选择问题的线性时间算法。如:当要选择最大元素或最小元素时,显然可以在O(n)时间完成。如果k <= n/logn,通过堆排序算法可以在O(n + klogn) = O(n)时间内找出第k小元素。当k >= n - n/logn时也一样。
一般的选择问题,特别是中位数的选择问题似乎比最小(大)元素要难。但实际上,从渐近阶的意义上,它们是一样的。也可以在O(n)时间完成。
下面我们用两种方法进行求解。
第一种:分治算法RandomizedSelect
思想:调用了随机划分函数RandomizedPartition,所以这个分治算法也是一个随机化的算法。
通过将其划分,我们逐渐可以缩小查找的范围进行查找。
时间复杂度:一般情况下为O(n),最坏情况下,数字有序且找最大的数,则为O(n)
代码:
#include#include#include#include#include#includeusing namespace std;
templateint Partition(Type *ar,int left,int right)
{
int i = left, j = right;
Type tmp = ar[i];
while(itmp) --j;
if(iint RandPartition(Type *ar,int left,int right)
{
//Sleep(800);
srand(time(NULL));
int pos = (rand() % (right - left + 1)) + left;
swap(ar[pos],ar[left]);
return Partition(ar,left