前言:今天早上来实验室,同桌问了我一个问题:找出一个数组里面前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个最大数相关推荐

  1. 典型的Top K算法_找出一个数组里面前K个最大数

    原文 典型的Top K算法_找出一个数组里面前K个最大数...或找出1亿个浮点数中最大的10000个...一个文本文件,找出前10个经常出现的词,但这次文件比较长,说是上亿行或十亿行,总之无法一次读入 ...

  2. 用JavaScript去找出一个数组里的所有素数(质数)

    varx, //定义一个变量xr, arr = []; //定义一个空数组 for (x = 1; x < 100; x++) {arr.push(x); //把1-100依次放到数组arr中 ...

  3. 找出一个数组中出现次数最多的那个元素

    Description 找出一个数组中出现次数最多的那个元素 Input 多组输入,请处理到文件结束 每组第一行输入一个整数n(不大于20) 第二行输入n个整数 Output 找出n个整数中出现次数最 ...

  4. 找出一个数组中唯一一个出现2次的数字

    找出一个数组中唯一一个出现2次的数字,不清楚是不是LeetCode上的题.本人默认是LeetCode上的题. 一个数组中有N个数字,但是只有一个数字出现了2次,其他的数字均不相同.这种问题一般应该采用 ...

  5. 如何快速找出一个数组中最大数和第二大数

    看到一道题是:快速找出一个数组中最大数和第二大数. 我之前学了一些数组排序,例如冒泡排序,简单选择排序等等,然后我就想可不可以利用冒泡排序来实现呢?之前写过冒泡排序实现从小到大的排列,那么可以改成从大 ...

  6. 快速找出一个数组中的最大数、第二大数

    http://blog.csdn.net/hackbuteer1/article/details/8035261#comments 快速找出一个数组中的最大数.第二大数 思路:如果当前元素大于最大数 ...

  7. 快速找出一个数组中的两个数字,让这两个数字之和等于一个给定的值

    我觉得写得很清晰,希望没有侵犯作者的著作权,原文地址http://blog.csdn.net/hackbuteer1/article/details/6699642 快速找出一个数组中的两个数字,让这 ...

  8. c语言找出一个数组中出现次数最多的那个元素,c语言找出数组中出现次数最多地那个元素...

    matlab中如何找出不同维度矩阵出现次数最多的数组并记录其个数 首先是胞矩阵中的序列问题,不妨假设AA{1}是一个多行两列的数据,AA{2}同例.程序如下clcclearallAA{1}=[12;2 ...

  9. [基础题]1.快速找出一个数组中的最大数、第二大数。

    [基础题]1.快速找出一个数组中的最大数.第二大数. package HomeWork_10;public class Test_01 {public static void main(String[ ...

最新文章

  1. Android Studio Terminal 不是内部或外部命令,也不是可运行程序或批处理文件
  2. C# 在异步中使用HttpWebRequest出现的“正在终止线程”错误的解决方案
  3. 工程项目管理丁士昭第二版_2021年软考系统集成项目管理工程师知识点预习第十四章第二节...
  4. 微软新冠: 数据分析网站 COVID Insights
  5. UVALive 4225 Prime Bases 贪心
  6. zookeeper 命令
  7. JS创建对象的模式介绍
  8. html 360不识别,html 为什么在ie里显示正常在360浏览器不正常呢?
  9. pmw调光c语言程序,51单片机led灯渐变PWM调光(渐亮渐灭)C语言和汇编源程序
  10. (转) Hibernate持久化类与主键生成策略
  11. java三大框架增删改查_Java_Web三大框架之Hibernate增删改查
  12. 将JavaScript函数作为参数传递
  13. 对CMMI标准的简单理解
  14. 后危机时代,DCS的新征程
  15. STm32驱动74HC595引脚图时序图工作原理
  16. pycharm: Error: Cannot run program……
  17. python图片自动上色_老旧黑白片修复机——使用卷积神经网络图像自动着色实战(附PyTorch代码)...
  18. 第六章 利用数组处理批量数据
  19. @用Python的turtle库画一个奥运五环!
  20. 动态链接--打桩机制

热门文章

  1. 【eXtremeComponents总结系列】使用总结(转载)
  2. 金融行业为什么热衷于区块链技术?|智谷微报告
  3. 数字化转型专家专访:我们应该如何思考企业数据战略?
  4. 罗技驱动要开机启动吗?要怎么设置?
  5. Javaweb基于SSM的汽车维修管理系统
  6. linux的软件漏洞,Linux man 软件包漏洞
  7. 人机大战结局,为何日本公众的看法与我们不同?
  8. CSS字体、文本、列表属性样式
  9. 【安卓安全】透明代理定向抓APP包
  10. SpringBoot使用validator校验