C语言线性时间求解第k小,线性时间找到第k小的元素:快排应用与BFPRT算法

问题分析

面对这个问题,最简单的想法是对数据进行排序,然后根据下标即可找到第k小的元素,目前已知的排序算法的最低时间复杂度为

O(nlog⁡2log⁡2n)O(n\sqrt{\log_2 {\log_2 n}})

O(nlog2​log2​n​),但并不为人熟知。目前应用最广的排序算法的最低时间复杂度为

O(nlog⁡2n)O(n\log_2 n)

O(nlog2​n)。

但是,作为完美主义者的程序员,需要思考,找到第k小的元素一定需要排序吗?但除了寻找最大或最小的元素之外,我们似乎只能选择排序。那么能否只进行部分排序,便可找到第k小的元素呢?答案是显然的,只需要采用每一趟都能确定一个固定元素的排序算法即可。

思考

O(nlog⁡2n)O(n\log_2 n)

O(nlog2​n)的排序算法中有哪些算法每一趟可以确定一个固定元素,答案是快速排序和堆排序(不考虑锦标赛排序,堆排序是锦标赛排序的升级版)。这里以快速排序为例,方便引入后面介绍的BFPRT算法,不过还有一个原因是堆排序获取第k小的元素的时间复杂度是

O(n)O(n)

O(n)的概率小于快速排序。

快排应用

我们知道,快排每一趟都会有随机有一个元素处于最终位置上,故只需在快排中设置一个新的递归出口再加以微改便能返回第k小的元素。

代码如下:

这里采用的快排为随机化快速排序,没有了解过的的朋友可以看一下我的另外一篇博客:升级版快速排序——随机化快速排序

template

void partition(T array[],int left,int right,int& mid)

{

srand(time(0));

int i = left, j = right, move = rand() % (right - left + 1) + left;

T temp = array[move];

array[move] = array[left];

while (i != j)

{

while (array[j] > temp&&j > i) j--;

if (i < j) array[i++] = array[j];

while (array[i] < temp&&i < j) i++;

if (i < j) array[j--] = array[i];

}

array[i] = temp;

mid = i;

}

template

T random_quick_sort(T array[], int left, int right,int k)

{

if (k > right - left + 1) exit(7);

int i;

partition(array, left, right, i);

if (k == i - left + 1) return array[i];

else if (k > i - left + 1) return random_quick_sort(array, i + 1, right, k - i + left - 1);

else return random_quick_sort(array, left, i - 1, k);

}

这个算法的时间复杂度的确定需要用到指示器随机变量。

E[T(n)]=E[∑k=0n−1Xk(T(maxE[T(n)]=E[\sum_{k=0}^{n-1}X_k(T(max

E[T(n)]=E[∑k=0n−1​Xk​(T(max{

k,n−k−1k,n-k-1

k,n−k−1}

))+Θ(n)]))+\Theta(n)]

))+Θ(n)],最终得到

E[T(n)]=Θ(n)E[T(n)]=\Theta(n)

E[T(n)]=Θ(n),即该算法的时间复杂度的期望值为

O(n)O(n)

O(n)

但是存在最坏情况,即每一次划分只能划分出一个部分,即

T(n)=T(n−1)+Θ(n)T(n)=T(n-1)+\Theta(n)

T(n)=T(n−1)+Θ(n),由等差级数可以得到最坏情况下的时间复杂度为

O(n2)O(n^2)

O(n2)

BFPRT算法

不想写了,困了

重写了篇博客,内容和这一样,转到那边去吧:找到第k小的元素【top-k】:快排应用与BFPRT算法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值