关于利用快排思想求第K小数的分析

最近复习快排算法,记得当时最有意思的是可以用快排的partition函数求出第K小数

于是上网搜索一番,发现都只是贴出了代码。无奈只好自己研究了下

利用快排partition求第k小数不得不从partition函数开始说:

快速排序的思想是在一组待排序的数中,找出一个数作为分界,使得它前面的数都比它小,后面的数都比它大。这个数叫做枢轴

当求出一组数的枢轴以后,一组数就可以以枢轴为界限分成两组,我们可以递归的找出这两个组的枢轴,只到每组只有一个数

这里我们应该注意的是,partition函数返回的是枢轴在这组数中的位置,而这个位置,其实就是这组数排序之后的第i个数的位置

因此要求第k小数,就是求在数组排序之后,第k位上的数是多少

于是我们就可以利用partition函数写出我们的求第k小数的函数了

int findk(int arr[],int st,int end,int k){//我们的数组从0号元素开始
    if(k<0||st+k-1>end)return -1;//不存在第K小数
    if(st==end)return st;//只有一个元素
    int q = partition(arr,st,end);//这是枢轴的下标,我们需要知道它在[st..end]中是第几个
    int i = q-st+1;//枢轴是第i小数
    if(i==k)return i;//找到
    else if(i>k)return findk(arr,st,q-1,k);//如果第K小数小于第i小数,则应该在枢轴的左边继续找
    else return findk(arr,q+1,end,k-i);//如果第K小数大于第i小数,则应该在枢轴右边找,我们排除了前面i个数,第k小数变成了新的数组中第k-i个数
}

关于partition函数的代码我就不贴了,你来看这篇日志,前提就是会了快排吧。。



时间: 2024-08-02 02:47:30

关于利用快排思想求第K小数的分析的相关文章

数字在排序数组中出现的次数(剑指offer)利用快排思想(O(logn))

数字在排序数组中出现的次数 参与人数:1216时间限制:1秒空间限制:32768K 通过比例:28.43% 最佳记录:0 ms|0K(来自 ) 题目描述 统计一个数字在排序数组中出现的次数. 题意:首先数组是个已经排列的有序递增序列!统计一个数出现的次数,相当于在有序的序列里插入一个数,那么我只要确定插入的位置,利用快排的思想,也可以说是二分,如果在数组中找到k,那么左右拓展边界就可以确定,该数在数组中出现的次数了. 一些特殊情况可以特判!比如k小于数组最小数,或者大于数组最大数: class

快排思想求给定序列中第k大的数

思想:快排的思想就是每排一次,就会把一个数(也就是我们选定的那个key)放到它在这个序列中正确的位置,所以每排一次就返回这个数所在下标看它是不是我们所要找的那个数(对应下面代码的ret是否等于size-k) #include <iostream> #include <vector> int QuockSort(int* array, int size, int k,std::vector<int>& vtmparr) { int first = 0; int l

hdu 4289 利用最大流思想求图的最小割

http://acm.hdu.edu.cn/showproblem.php?pid=4289 Problem Description You, the head of Department of Security, recently received a top-secret information that a group of terrorists is planning to transport some WMD 1 from one city (the source) to anothe

基于快排思想的题目(一)——荷兰旗问题

基于快排思想的题目(一)--荷兰旗问题 快排的实现大家估计都知道,主要就是一个partition和交换的过程.这个思想其实是很巧妙的,基于此,很多题目都可以用它来很好地解决.这篇我们讲到了注明的荷兰旗问题,就是可以用到快排的思想~后续还有一系列的题目,应该都是可以用到快排思想的,后面慢慢整理ing~ 1. 题目描述 这个题目是由荷兰科学家Dijkstra提出来的,首先输入乱序排列的三色小球(红,白,蓝),如果通过两两交换,使得所有红色小球排在前面,白色小球排在中间,蓝色小球排在最后~ 2. 图文

HDU 2852 KiKi&#39;s K-Number(动态过程求第K小数)

题意: 给出三种操作, 0 在容器中插入一个数. 1 在容器中删除一个数. 2 求出容器中大于a的第k大元素. 思路:可以用树状数组和线段树,显然a[1]+...+a[i]随i有明显的单调性,所以可以二分出答案 线段树时间复杂度比树状数组的常数大了几倍...所以线段树擦边过了 还有另外一种思路:二分只是二分出a[1]+...+a[i]的上界i,所以可以逆向考虑,从a[1]开始累加,直到到达k,这样的复杂度就由原来的 O(lgN*lgN) 变成O(lgN)了.难在累加的过程,线段树和树状数组是同样

算法导论学习之线性时间求第k小元素+堆思想求前k大元素

对于曾经,假设要我求第k小元素.或者是求前k大元素,我可能会将元素先排序,然后就直接求出来了,可是如今有了更好的思路. 一.线性时间内求第k小元素 这个算法又是一个基于分治思想的算法. 其详细的分治思路例如以下: 1.分解:将A[p,r]分解成A[p,q-1]和A[q+1,r]两部分.使得A[p,q-1]都小于A[q],A[q+1,r]都不小于A[q]; 2.求解:假设A[q]恰好是第k小元素直接返回,假设第k小元素落在前半区间就到A[p,q-1]递归查找.否则到A[q+1,r]中递归查找. 3

HDU 5696 ——区间的价值——————【线段树、快排思想】

区间的价值 Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 662    Accepted Submission(s): 329 Problem Description 我们定义“区间的价值”为一段区间的最大值*最小值. 一个区间左端点在L,右端点在R,那么该区间的长度为(R−L+1). 现在聪明的杰西想要知道,对于长度为k的区间,最大

排序算法——快排思想

快速排序 1.思想 快速排序将一个数组分成两个数组,再对两个数组独立排序,是个递归算法. 首先随机选出一个切分元素temp(一般为这个数组的第一个元素),将小于temp的数放在temp的左边,将大于temp的数放在temp的右边. 快排和堆排序很像,他们都是将一个数组分成两个子数组,都属于递归算法.但是不同之处在于:快排空间复杂度为o(1),而堆排为o(n), 快排是原地排序,只需要一个很小的辅助栈,时间复杂度为NlogN. 2.代码实现(java) public class Quick {  

求两个有序序列合并成新有序序列的中位数,求第k小数

此算法涉及一个重要数学结论:如果A[k/2-1]<B[k/2-1],那么A[0]~A[k/2-1]一定在第k小的数的序列当中,可以用反证法证明. 更加一般的结论是:k=pa+pb,如果A[pa-1]<B[pb-1],那么A[0]~A[pa-1]一定在第k小的数的序列当中. 算法思想如下: 1,假设A长度为m,B长度为n,m>n,反之亦然. 2,拆分k=pa+pb. 3,如果A[pa-1]<b[pb-1],那证明第A[0]~A[pa-1]一定在合并后k小数序列中.所以,可以把A的前面