找出一个数组里面前K个最大数
来源:互联网 发布:个人日志提醒软件 编辑:程序博客网 时间:2024/05/18 02:08
前言:今天早上来实验室,同桌问了我一个问题:找出一个数组里面前K个最大数的高效算法。最近正好在看数据结构和算法相关内容,便以己之力帮她思考了思考。
问题:找出一个数组里面前K个最大数。
解法:
1.第一感觉就是对数组进行降序全排序,然后返回前K个元素,即是需要的K个最大数。
排序算法的选择有很多,考虑数组的无序性,可以考虑选择快速排序算法,其平均时间复杂度为O(NLogN)。具体代码实现可以参见相关数据结构与算法书籍。
2.观察第一种算法,问题只需要找出一个数组里面前K个最大数,而第一种算法对数组进行全排序,不单单找出了前K个最大数,更找出了前N(N为数组大小)
个最大数,显然该算法存在“冗余”,因此基于这样一个原因,提出了改进的算法二。
首先建立一个临时数组,数组大小为K,从N中读取K个数,降序全排序(排序算法可以自行选择,考虑数组的无序性,可以考虑选择快速排序算法),然后依
次读入其余N - K个数进来和第K名元素比较,大于第K名元素的值则插入到合适位置,数组最后一个元素溢出,反之小于等于第K名元素的值不进行插入操作。
只待循环完毕返回临时数组的K个元素,即是需要的K个最大数。同算法一其平均时间复杂度为O(KLogK + (N - K))。具体代码实现可以自行完成。
算法时间复杂度证明:
原问题:
顺序统计量选择问题:数组A包含N个元素,找出数组A中前K个最大数
解法二:
首先建立一个临时数组,数组大小为K,从N中读取K个数,降序全排序(可以考虑选择快速排序算法,快排平均复杂度O(KlogK)),
然后依次读入其余N - K个数进来和第K名元素比较,大于第K名元素的值则插入到合适位置,数组最后一个元素溢出,反之小于等于第K名元素的值不进行插入操作。
只待循环完毕返回临时数组的K个元素,即是需要的K个最大数。
其平均时间复杂度为O(KLogK + (N - K))。
证明:
设指示器随机变量
Xi = {A属于前K个最大数},i=K+1, K+2, ..., N;
由于数组A的N个元素分布随机,则E[Xi] = 1/N;
则依次处理其余N - K个数的时间复杂度为T(N-K) = sum(Xi*logK),i=K+1, K+2, ..., N;
(注意logK是将一个数插入到排好序的K个数的时间复杂度)
对上式求期望,得
E[T(N-K)] = E[sum(Xi*logK),i=K+1, K+2, ..., N]
= sum(E[Xi] * logK),i=K+1, K+2, ..., N
= sum(1/n * logK),i=K+1, K+2, ..., N
= (N-K)logK/n < N-K;
综合,该算法平均时间复杂度为
T(N) = O(KLogK + (N - K))。
3.上面两种算法在N=100万,K=50万时速度都尤其“漫长“,现在提出一种更高效的算法,该算法原理和快速排序一致,但只有一个方向的递归,其平均时间
复杂度为O(N)。
先选取一个中值元素(该中值是否合理将影响到算法效率,其原因同快速排序),然后将大于等于该数的元素放到其右侧,小于该数的放到左侧。如7 4 6 8 0
-1,选取6作为中值元素,则结果应该为4 0 -1 6 8 7,接下来比较K值和现在的中值元素6所在索引(3)。
如果K小于索引3,则处于包括中值元素在内的右边的元素即是前K个最大数中的前(3(索引) - K + 1)个最大数,予以保存,同时需在索引0 ~ 2间再进行递归操作继续选取第K名。
如果K大于索引3,则在4 ~ 5中递归选取第K - 3(索引) - 1名即可。
还有一关键是可以为递归中的数组长度选取一临界点,小于该临界则进行全排序,而不再进行递归操作。
以上算法均是本人在书本上或者互联网上学习的算法,并非自己原创,当然部分的改动还是自我原创的。
其实当问题规模不是很大时,比如数组大小N很小,N为100数量级,可以不用太追求算法的高效性,因为对于问题规模不大时,上面三种算法的运行时间相差并不大,
完全可以考虑采用第一种或者第二种比较简单的实现方式。
- 找出一个数组里面前K个最大数
- 找出一个数组里面前K个最大数
- 典型的Top K算法_找出一个数组里面前K个最大数
- 典型的Top K算法_找出一个数组里面前K个最大数...或找出1亿个浮点数中最大的10000个...一个文本文件,找出前10个经常出现的词,但这次文件比较长,说是上亿行或十亿行,总之无法一次读入内存,
- 典型的Top K算法_找出一个数组里面前K个最大数...或找出1亿个浮点数中最大的10000个...一个文本文件,找出前10个经常出现的词,但这次文件比较长,说是上亿行或十亿行,总之无法一次读入内存,
- 典型的Top K算法_找出一个数组里面前K个最大数...或找出1亿个浮点数中最大的10000个...一个文本文件,找出前10个经常出现的词,但这次文件比较长,说是上亿行或十亿行,总之无法一次读入内存
- 典型的Top K算法_找出一个数组里面前K个最大数...或找出1亿个浮点数中最大的10000个...一个文本文件,找出前10个经常出现的词,但这次文件比较长,说是上亿行或十亿行,总之无法一次读入内存,
- 典型的Top K算法 _找出一个数组里面前K个最大数_找出1亿个浮点数中最大的10000个_一个文本文件,找出前10个经常出现的词,但这次文件比较长,说是上亿行或十亿行,总之无法一次读入内存.
- 典型的Top K算法_找出一个数组里面前K个最大数...或找出1亿个浮点数中最大的10000个...一个文本文件,找出前10个经常出现的词,但这次文件比较长,说是上亿行或十亿行,总之无法一次读入内存,
- n个元素的数组中找出前K个最大数最有效算法O(nlg(k))
- 找出数组中第K个最大的数
- 使用优先级队列求一个大数组中的前k个最大的数(或前k个最小的数)
- ms 两个数组,从每个数组中取一个数相加,求最大的前k个和
- BFPRT算法——在一个无序数组找出前k小的数
- 从一个长度为n的数组中找出前k个最小值的最优实现
- Java如何找出数组中前k个高频元素
- Java如何找出数组中前k个高频元素
- 从数组中找出最大的前两个数
- android系统移植要点之四--以6410为例
- 程序员技术练级攻略
- 1300 竞赛报名
- C#程序实现动态调用DLL的研究
- 读取随机函数的js
- 找出一个数组里面前K个最大数
- 项目总结
- 富裕的态度
- 1302 导弹拦截
- 依赖注入 控制反转Ioc
- php学习
- makefile报错 warning: ignoring old commands for target
- 正则表达式之身份证号验证
- android系统移植要点之五--以6410为例