03寻找最小的k个数
题目描述:查找最小的k个元素
题目:输入n个整数,输出其中最小的k个。
例如输入1,2,3,4,5,6,7和8这8个数字,则最小的4个数字为1,2,3和4。
1:最简单直白的思路是,要求一个序列中最小的k个数,按照惯有的思维方式,很简单,先对这个序列从小到大排序,然后输出前面的最小的k个数即可。
至于选取什么的排序方法,可能会第一时间想到快速排序,我们知道,快速排序平均所费时间为n*logn,然后再遍历序列中前k个元素输出,即可,总的时间复杂度为O(n*logn+k) =
O(n*logn)。
线性时间的排序,即计数排序,时间复杂度虽能达到O(n),但限制条件太多,不常用。
2:再进一步想想,题目并没有要求要查找的k个数,甚至后n-k个数是有序的,既然如此,咱们又何必对所有的n个数都进行排序列?
这时,可以如此:即遍历n个数,先把最先遍历到得k个数存入大小为k的数组之中,对这k个数,利用选择或交换排序,找到k个数中的最大数kmax,用时O(k),后再继续遍历后n-k个数,x与kmax比较:如果x>kmax,则不更新数组;如果x<kmax,则x代替kmax,并再次重新找出k个元素的数组中最大元素kmax’。(这样,被交换出的kmax至少大于k个数,所以肯定不是最终结果中的数。)这样,整趟下来,总的时间复杂度平均下来为:n*O(k)=
O(n*k)。
上述思想的一个优化,就是维护k个元素的最大堆(大小是k),原理与上述第方案一致,即用容量为k的最大堆存储最先遍历到的k个数,建堆费时O(k)后。继续遍历数列,每次遍历一个元素x,与堆顶元素比较,x<kmax,更新堆(用时logk),否则不更新堆。这样下来,总费时O(k+(n-k)*logk)=O(n*logk)。此方法得益于在堆中,查找等各项操作时间复杂度均为logk。
3:实际上,可以用最小堆初始化数组(大小是n,不是k),然后取这个优先队列前k个值。复杂度O(n)+k*O(log n)。建堆所用时间为O(n),然后取堆中的前k个数,总的时间复杂度即为:O(n+k*logn)。至于该思路的时间是否小于上述思路的O(n*logk),即O(n+k*logn)
<O(n*logk) ? 可以这么解决:当k是常数,n趋向于无穷大时,求(n*logk)/(n+k*logn)的极限T,如果 T>1,那么可得O(n+k*logn)< O(n*logk)。最终证明的确如此,这个极值T=logk>1,即采取建立n个元素的最小堆后取其前k个数的方法的复杂度小于采取常规的建立k个元素最大堆后通过比较寻找最小的k个数的方法的复杂度。
事实上,是建立最大堆还是建立最小堆,其实际的程序运行时间相差并不大,运行时间都在一个数量级上。但是当n比较大时(海量数据),那么需要将n个数都建立最小堆,这个时候,就不如建立k个元素的最大堆适用了。
4:算法导论第9章,曾介绍RANDOMIZED-SELECT(A,p, r, i)算法,该算法可以寻找第i小的数,该算法用类似快速排序的划分方法,N个数存储在数组S中,再从数组中随机选取一个数X,把数组划分为Sa和Sb俩部分,Sa<=X<=Sb,如果i小于Sa的元素个数,则递归调用RANDOMIZED-SELECT(A,p,
q-1, i),否则调用RANDOMIZED-SELECT(A, q+1, r, i-k)。
采用这个算法得到第k小的元素之后,就可以在线性时间内找到所有最小的k个元素:
a:找到了第K小的数X后,再遍历一次数组,找出所有比X小的元素,需要O(N)的时间(比较Xk与数组中各数的大小,凡是比Xk小的元素,都是我们要找的元素)。这个结论非常之简单,也无需证明。
b:找到第k小的元素X后,因为讨论都是基于快速排序的partition方法,而这个方法,每次划分之后,都保证了枢纽元素X的前边元素统统小于Xk,后边元素统统大于Xk。所以,算法本身,在找到第k小的元素之后,之前的元素就是所有最小的k个元素。
RANDOMIZED-SELECT,以序列中随机选取一个元素作为主元,可达到线性期望时间O(N)的复杂度。SELECT,快速选择算法,以序列中“五分化中项的中项”,或“中位数的中位数”作为主元(枢纽元),则不容置疑的可保证在最坏情况下亦为O(N)的复杂度。
至于RANDOMIZED-SELECT(A, p, r, i)算法,以及最坏情况下为O(n)的SELECT算法,算法导论第9章都有详述,不再赘述。
http://blog.csdn.net/v_JULY_v/article/details/6370650
03寻找最小的k个数的更多相关文章
- 算法练习:寻找最小的k个数
参考July的文章:http://blog.csdn.net/v_JULY_v/article/details/6370650 寻找最小的k个数题目描述:查找最小的k个元素题目:输入n个整数,输出其中 ...
- 算法笔记_035:寻找最小的k个数(Java)
目录 1 问题描述 2 解决方案 2.1 全部排序法 2.2 部分排序法 2.3 用堆代替数组法 2.4线性选择算法 1 问题描述 有n个整数,请找出其中最小的k个数,要求时间复杂度尽可能低. 2 ...
- Java实现寻找最小的k个数
1 问题描述 有n个整数,请找出其中最小的k个数,要求时间复杂度尽可能低. 2 解决方案 2.1 全部排序法 先对这n个整数进行快速排序,在依次输出前k个数. package com.liuzhen. ...
- 寻找最小的k个数(四种方法)
1 使用从大到小的优先队列保存最小的K个数,每次取出K个数之后的其余数和堆顶元素比较,如果比堆顶元素小,则将堆顶元素删除,将该元素插入 void topK(int arr[],int n,int k) ...
- 编程之法:面试和算法心得(寻找最小的k个数)
内容全部来自编程之法:面试和算法心得一书,实现是自己写的使用的是java 题目描述 输入n个整数,输出其中最小的k个. 分析与解法 解法一 要求一个序列中最小的k个数,按照惯有的思维方式,则是先对这个 ...
- 算法练习-寻找最小的k个数
练习问题来源 https://wizardforcel.gitbooks.io/the-art-of-programming-by-july/content/02.01.html 要求 输入n个整数, ...
- 寻找最小的k个数
1. 能想到的最直接的办法,就是对数组进行排序,最好的排序算法的时间复杂性为O(n*logn),这一个方法请参照各种排序算法. 2. 另外申请一个k空间数组,依次更改里面的最大值,每做一次最多要扫描一 ...
- 每日一题 - 剑指 Offer 40. 最小的k个数
题目信息 时间: 2019-06-30 题目链接:Leetcode tag: 快排 难易程度:中等 题目描述: 输入整数数组 arr ,找出其中最小的 k 个数.例如,输入4.5.1.6.2.7.3. ...
- 窥探算法之美妙——寻找数组中最小的K个数&python中巧用最大堆
原文发表在我的博客主页,转载请注明出处 前言 不论是小算法或者大系统,堆一直是某种场景下程序员比较亲睐的数据结构,而在python中,由于数据结构的极其灵活性,list,tuple, dict在很多情 ...
随机推荐
- 建筑设计类软件整理ACDSee,PS,CAD,Ecotect,SketchUp,Phoenics,Revit,Rhino,
关于建筑设计类软件整理 1 建筑设计类专业最常用软件如下,包括SU,CAD, REVIT,PS等. 2 sketch up 简称SU,中文名草图大师,在推敲方案,拉推体块时有着不可或缺的作用,而且随着 ...
- Dockerfile 编写
转: https://blog.fundebug.com/2017/05/15/write-excellent-dockerfile/如何编写最佳的Dockerfile 译者按: Dockerfile ...
- JSP内置对象解析
out对象:(PrintWriter类的实例) 用来向客户端输出信息,除了输出各种信息外还负责对缓冲区进行管理: 主要方法: print / println void 输出数据 newLine() v ...
- jsp必填项加红色星号
<th><font color=red>*</font>文字:</th>
- UE4物理模块(三)---碰撞查询(下)SAP/MBP/BVH算法简介
在上一文中介绍了碰撞查询的配置方法: Jerry:UE4物理模块(三)---碰撞查询(上)zhuanlan.zhihu.com 本篇介绍下UE4的各种零大小的射线检测,以及非零大小(带体积)的射线检 ...
- django中模型
一.django需要使用数据库,则需要安装对应的驱动,比如mysql,则需要安装mysqlclient驱动: pip install mysqlclient 二.在settings.py文件中配置数据 ...
- LintCode_175 翻转二叉树
题目 翻转一棵二叉树 您在真实的面试中是否遇到过这个题? Yes 样例 1 1 / \ / \ 2 3 => 3 2 / \ 4 4 和前序遍历代码很相似从叶子节点依次翻转递归到根节点C++代码 ...
- LintCode_181 将整数A转换为B
题目 如果要将整数A转换为B,需要改变多少个bit位? 如把31转换为14,需要改变2个bit位. ()10=()2 ()10=()2 思路 要考虑负数的问题 如果 一正一负 将他们去全部变成正数 后 ...
- 春蔚专访--MaxCompute 与 Calcite 的技术和故事
摘要:2019大数据技术公开课第一季<技术人生专访>,来自阿里云计算平台事业部高级开发工程师雷春蔚向大家讲述了MaxCompute 与 Calcite 的技术和故事. 具体内容包括: 1) ...
- 【软件安装】我喜欢的notepad插件
1.文件管理器 explorer 2.16进制查看文件工具 HEX-Editor