Random Select Problem(数组中前k大数问题)
来源:互联网 发布:知天下帐号 编辑:程序博客网 时间:2024/04/29 21:10
所谓“第(前)k大数问题”指的是在长度为n(n>=k)的乱序数组中S找出从大到小顺序的第(前)k个数的问题。
转自(http://www.cppblog.com/superKiki/archive/2011/04/10/143858.html)
解法1:我们可以对这个乱序数组按照从大到小先行排序,然后取出前k大,总的时间复杂度为O(n*logn+k)。
解法2:利用选择排序或交互排序,K次选择后即可得到第k大的数。总的时间复杂度为O(n*k)
解法3:利用快速排序的思想,从数组S中随机找出一个元素X,把数组分为两部分Sa和Sb。Sa中的元素大于等于X,Sb中元素小于X。这时有两种情况:
1.Sa中元素的个数小于k,则Sb中的第k-|Sa|个元素即为第k大数;
2.Sa中元素的个数大于等于k,则返回Sa中的第k大数。时间复杂度近似为O(n)
///////////
回忆一下快速排序,快排中的每一步,都是将待排数据分做两组,其中一组的数据的任何一个数都比另一组中的任何一个大,然后再对两组分别做类似的操作,然后继续下去……
在本问题中,假设N个数存储在数组S中,我们从数组S中随机找出一个元素X,把数组分为两部分Sa和Sb。Sa中的元素大于等于X,Sb中元素小于X。
这时,有两种可能性:
1. Sa中元素的个数小于K,Sa中所有的数和Sb中最大的K-|Sa|个元素(|Sa|指Sa中元素的个数)就是数组S中最大的K个数。
2. Sa中元素的个数大于或等于K,则需要返回Sa中最大的K个元素。
这样递归下去,不断把问题分解成更小的问题,平均时间复杂度O(N * log2K)。
解法4:二分[Smin,Smax]查找结果X,统计X在数组中出现,且整个数组中比X大的数目为k-1的数即为第k大数。时间复杂度平均情况为O(n*logn)
解法5:用O(4*n)的方法对原数组建最大堆,然后pop出k次即可。时间复杂度为O(4*n+k*logn)
解法6:维护一个k大小的最小堆,对于数组中的每一个元素判断与堆顶的大小,若堆顶较大,则不管,否则,弹出堆顶,将当前值插入到堆中。时间复杂度O(n*logk)
解法7:利用hash保存数组中元素Si出现的次数,利用计数排序的思想,线性从大到小扫描过程中,前面有k-1个数则为第k大数,平均情况下时间复杂度O(n)
//////////////
上面类快速排序的方法平均时间复杂度是线性的。能否有确定的线性算法呢?是否可以通过改进计数排序、基数排序等来得到一个更高效的算法呢?答案是肯定的。但算法的适用范围会受到一定的限制。
如果所有N个数都是正整数,且它们的取值范围不太大,可以考虑申请空间,记录每个整数出现的次数,然后再从大到小取最大的K个。比如,所有整数都在(0, MAXN)区间中的话,利用一个数组count[MAXN]来记录每个整数出现的个数(count[i]表示整数i在所有整数中出现的个数)。我们只需要扫描一遍就可以得到count数组。然后,寻找第K大的元素。
- Random Select Problem(数组中前k大数问题)
- 海量数据中找出前k大数(topk问题)
- 海量数据中找出前k大数(topk问题)
- 海量数据中找出前k大数(topk问题)
- 第(前)k大数问题
- 第(前)k大数问题
- 第(前)k大数问题
- 【Top-k问题】如何从海量数据中找出前k大数
- 寻找前K大数
- 数组中出现次数第k多的数字(求次数前k多的问题)
- 寻找无序数组中的第K大数和前K大数
- 大数组中获取K个大数
- 求数组中第K大数
- 寻找数组中第K大数
- 数组中求第K大数
- 数组中求第K大数
- 数组中求第K大数
- 数组中求第K大数
- bzoj2741
- jQuery选择器:nth-child(even) 与:even的区别
- 白乔原创:VC之控件篇
- simpleCursorAdapter刷新
- ASF文件结构
- Random Select Problem(数组中前k大数问题)
- hibernate 锁
- JndiTemplate bean配置笔记
- 有一段时间没有写blog了
- 链表笔试题
- 作品展问题总结
- asf认识
- 【通信】电信业务
- 在shell脚本中调用另一个脚本的三种不同方法(fork, exec, source)