从一堆无序的数中(共n个数)找到最小的K个数,这也算是一道比较经典的题目了,关于这道题目的解法,一般有几种:

方法1:先对所有的数据进行排序,然后直接找出前K个数来,即最小的K个数。时间复杂度为O(N*logN)。

方法2:采用类似快排的思想,只要找到第K小的数值的位置的话,那么数组中的前K个数值一定是最小的K个数,但是这K个数不一定是排好序的,关于找到第K个小的数值的方法卡参考我之前的文章:http://www.cnblogs.com/wangkundentisy/p/8810077.html

当然,也可以参考《剑指offer(第二版)》面试题40。这种方法的期望时间复杂度为O(N),但是适用于大多数情况;最坏情况下时间复杂度可达到O(N^2)。

方法3:利用一个大顶堆,具体过程如下:

  选取数据中前K个数(或者任意K个数)构成一个大顶堆,这个堆的根节点就是这K个数中的最大值,然后从剩余的n-K个数中依次找一个数与根节点的数比较,如果比根节点的数大的话,则跳过;如果比根节点的数小的话,就把根节点删除,并把这个数值加入到这个堆中,然后再把这个堆调整成大顶推,重复上述过程,直到比较完剩余的n-k个数。

这种方法的时间复杂度为O(N*logK)。

方法4:利用堆排序的思想,建立一个大小为n的小顶堆,由于小顶堆的顶点一定是n个数中的最小值,所以每次删除根节点,然后在调整堆,重复K次,就能找到最小的K个值了。(与堆排序的过程一致)这种算法的时间复杂度为O(K*logN)。

==================================================================================================分割线=================================================

1.当n的值不是很大时,以上几种方法的性能相差并不是很大,通常方法2用的比较多。 

2.那么当n很大的时候,方法1和方法2就不适用了。通常采用方法3。(关于海量数据处理的问题可参考july的博客:https://blog.csdn.net/v_july_v/article/details/7382693)那么,为什么不能采用方法4呢?以下是个人的一些见解:

在n非常大的时候,数据需要存到硬盘上,而K相对却很小,采用方法3的话,可以在内存上轻易维护大小为K的堆的情况下,在减少磁盘I/O上会有一定的优势,因为每个元素只需要被读取一次。即方法3只需将大小为K的堆写入内存,而方法4需要将所有的n个数据写入内存,相比而言方法3对内存要求更小,更具有优势。所以,在有限的资源下,海量数据处理问题,通常采用方法3.

关于“最小的K个数”问题的更多相关文章

  1. 剑指Offer面试题:27.最小的k个数

    一.题目:最小的k个数 题目:输入n个整数,找出其中最小的k个数.例如输入4.5.1.6.2.7.3.8这8个数字,则最小的4个数字是1.2.3.4. 这道题是典型的TopK问题,其最简单的思路莫过于 ...

  2. 算法练习:寻找最小的k个数

    参考July的文章:http://blog.csdn.net/v_JULY_v/article/details/6370650 寻找最小的k个数题目描述:查找最小的k个元素题目:输入n个整数,输出其中 ...

  3. 剑指Offer:面试题30——最小的k个数(java实现)

    问题描述: 输入n个整数,找出其中最小的k个数 思路1: 先排序,再取前k个 时间复杂度O(nlogn) 下面给出快排序的代码(基于下面Partition函数的方法) public void Quic ...

  4. 输入一个数组,求最小的K个数

    被这道题困了好久,看了剑指Offer才知道OJ上的要求有点迷惑性. 题目: 输入n个整数,找出其中最小的K个数.例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4. 一 ...

  5. 1046: 最小的K个数

    1046: 最小的K个数 时间限制: 1 Sec  内存限制: 128 MB提交: 233  解决: 200[提交][状态][讨论版] 题目描述 输入n个整数,找出其中最小的K个数.例如输入4,5,1 ...

  6. 最小的K个数:用快排的思想去解相关问题

    实现快速排序算法的关键在于先在数组中选择一个数字,接下来把数组中的数字分为两部分,比选择的数字小的数字移到数组的左边,比选择的数字大的数字移到数组的右边. 这个函数可以如下实现: int Partit ...

  7. 剑指offer面试题30:最小的k个数

    一.题目描述 输入n个整数,找出其中最小的K个数.例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,. 二.解题思路 1.思路1 首先对数组进行排序,然后取出前k个数 ...

  8. 最小的k个数

    // 最小的k个数.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <iostream> #include & ...

  9. 窥探算法之美妙——寻找数组中最小的K个数&python中巧用最大堆

    原文发表在我的博客主页,转载请注明出处 前言 不论是小算法或者大系统,堆一直是某种场景下程序员比较亲睐的数据结构,而在python中,由于数据结构的极其灵活性,list,tuple, dict在很多情 ...

  10. 求一个数组中最小的K个数

    方法1:先对数组进行排序,然后遍历前K个数,此时时间复杂度为O(nlgn); 方法2:维护一个容量为K的最大堆(<算法导论>第6章),然后从第K+1个元素开始遍历,和堆中的最大元素比较,如 ...

随机推荐

  1. 使用rsync, 向另外一台服务器同步目录和文件的脚本

    #!/bin/bash #亚特兰蒂斯-同步目录#定时任务ini_file="/usr/local/sunlight/conf/rsync-file.ini"target_ip=&q ...

  2. Linux命令学习之路——变更文档拥有者:chown

    使用权限:root用户 使用方式:chown [ -cvfRh ] [ --help ] [ --version ] user[ :group ] file... 作用:该命令用于改变文档的拥有者 注 ...

  3. Python 金融数据分析库及相关框架

    BackTest框架库: PyAlgoTrade ZipLine 金融数据分析库: pandas

  4. xdoj-1057(Lucas定理的证明及其模板)

    Lucas定理的证明: 转自百度百科(感觉写的还不错) 首先你需要这个算式:    ,其中f > 0&& f < p,然后 (1 + x) nΞ(1 + x) sp+q Ξ ...

  5. Go Example--map

    package main import "fmt" func main() { //初始化map make(map[类型][类型]) m:= make(map[string]int ...

  6. 【liunx】时间处理函数

    一.脚本示例 [mylinuxaccount@linux01 ~]$ date +%Y%m%d 20171224 [mylinuxaccount@linux01 ~]$ date +%F 2017-1 ...

  7. Hibernate(二)

    性能分析 抓取策略 研究对象 研究怎么样提取集合的,该策略应该作用与set元素上 研究从一的一方加载多的一方 案例 查询cid为1的班级的所有的学生 明:通过一条sql语句:左外链接,把classes ...

  8. solr 5.0.0 bin/start脚本详细解析

    参考文档:https://cwiki.apache.org/confluence/display/solr/Solr+Start+Script+Reference#SolrStartScriptRef ...

  9. lch 儿童围棋课堂 启蒙篇 (李昌镐 著)

    第1章 了解围棋 第2章 无气不活 棋子的"气"第3章 有目数才能赢空第4章 常用术语第5章 吃子第6章 死活:眼第7章 死活:典型棋形第8章 布局:术语篇 第1章 了解围棋 (已 ...

  10. Python实例属性限制(__slots__)

    Python的动态绑定可以在程序运行的过程中对实例或class加上功能,但是如果我们想要限制实例的属性怎么办呢?更改内容请参考:Python学习指南 正常情况下,当我们定义了一个class,创建了一个 ...