当前位置:三九宝宝网 → 宝宝成长 → 经典故事 → 正文

一道经典的面试题:如何从N个数中选出最大小的n个数

更新:01-06 整理:39baobao.com
字体:

[如意算盘是哪几个数字的成语]如意算盘是哪几个数字的成语——1、6、8。 如意算盘 rú yì suàn pán 【解释】比喻考虑问题时从主观愿望出发,只从好的方面着想打算。 【出处】清·李宝嘉《官场现形记》...+阅读

这个问题我前前后后考虑了有快一年了,也和不少人讨论过。据我得到的消息,Google和微软都面过这道题。这道题可能很多人都听说过,或者知道答案(所谓的堆),不过我想把我的答案写出来。我的分析也许存有漏洞,以交流为目的。但这是一个满复杂的问题,蛮有趣的。看完本文,也许会启发你一些没有想过的解决方案(我一直认为堆也许不是最高效的算法)。

在本文中,将会一直以寻找n个最大的数为分析例子,以便统一。注:本文写得会比较细节一些,以便于绝大多数人都能看懂,别嫌我罗嗦:) 我很不确定多少人有耐心看完本文!Naive 方法:首先,我们假设n和N都是内存可容纳的,也就是说N个数可以一次load到内存里存放在数组里(如果非要存在链表估计又是另一个challenging的问题了)。从最简单的情况开始,如果n=1,那么没有任何疑惑,必须要进行N-1次的比较才能得到最大的那个数,直接遍历N个数就可以了。

如果n=2呢?当然,可以直接遍历2遍N数组,第一遍得到最大数max1,但是在遍历第二遍求第二大数max2的时候,每次都要判断从N所取的元素的下标不等于max1的下标,这样会大大增加比较次数。对此有一个解决办法,可以以max1为分割点将N数组分成前后两部分,然后分别遍历这两部分得到两个最大数,然后二者取一得到max2。也可以遍历一遍就解决此问题,首先维护两个元素max1,max2(max1=max2),取到N中的一个数以后,先和max1比,如果比max1大(则肯定比max2大),直接替换max1,否则再和max2比较确定是否替换max2。

采用类似的方法,对于n=2,3,4一样可以处理。这样的算法时间复杂度为O(nN)。当n越来越大的时候(不可能超过N/2,否则可以变成是找N-n个最小的数的对偶问题),这个算法的效率会越来越差。但是在n比较小的时候(具体多小不好说),这个算法由于简单,不存在递归调用等系统损耗,实际效率应该很不错.堆:当n较大的时候采用什么算法呢?首先我们分析上面的算法,当从N中取出一个新的数m的时候,它需要依次和max1,max2,max3max n比较,一直找到一个比m小的max x,就用m来替换max x,平均比较次数是n/2。

可不可以用更少的比较次数来实现替换呢?最直观的方法是,也就是网上文章比较推崇的堆。堆有这么一些好处:1.它是一个完全二叉树,树的深度是相同节点的二叉树中最少的,维护效率较高;2.它可以通过数组来实现,而且父节点p与左右子节l,r点的数组下标的关系是s[l] = 2*s[p]+1和s[r] = 2*s[p]+2。在计算机中2*s[p]这样的运算可以用一个左移1位操作来实现,十分高效。

再加上数组可以随机存取,效率也很高。3.堆的Extract操作,也就是将堆顶拿走并重新维护堆的时间复杂度是O(logn),这里n是堆的大小。具体到我们的问题,如何具体实现呢?首先开辟一个大小为n的数组区A,从N中读入n个数填入到A中,然后将A维护成一个小顶堆(即堆顶A[0]中存放的是A中最小的数)。然后从N中取出下一个数,即第n+1个数m,将m与堆顶A[0]比较,如果m

本文地址:https://www.39baobao.com/show/14_21120.html

以上内容来自互联网,请自行判断内容的正确性。若本站收录的信息无意侵犯了贵司版权,请联系我们,我们会及时处理和回复,谢谢.

以下为关联文档:

数字一到十开头的成语接龙每个数字接龙至少十个成语一刻千金 今非昔比 比比皆是 事半功倍 背道而驰 持之以恒 横冲直撞 壮志凌云 芸芸众生 生搬硬套二三其得 德高望重 众望所归 归心似箭 见异思迁 千方百计 记忆犹新 心中有数...

给几个数学小故事知识唐僧师徒摘桃子 一天,唐僧命徒弟悟空、八戒、沙僧三人去花果山摘些桃子。不长时间,徒弟三人摘完桃子高高兴兴回来。师父唐僧问:你们每人各摘回多少个桃子? 八戒憨笑着说:师父,我来...

帮我找5个数学小故事语言要简洁明了数学危机 由毕达哥拉斯提出的著名命题“万物皆数”是该学派的哲学基石。而“一切数均可表成整数或整数之比”则是这一学派的数学信仰。然而,具有戏剧性的是由毕达哥拉斯建立...

帮我找5个数学小故事语言要简洁1·小 鸡 的 家 小鸭要到小鸡家做客,可是它不认识小鸡的家,小白兔跑过来说:“让我告诉你小鸡家怎么走。”小鸭按照小白兔告诉它的方向,先往北走第一个路口往西走,过一条马路往东...

个数字排序的C语言程序汗,。。。。。任意一本家才上都有 什么冒泡 选择 插入排序都是啊 、排序算法 (1)分析 因为每一趟排序都使有序区增加了一个气泡,在经过n-1趟排序之后,有序区中就有n-1个气泡,而...

c语言程序编写经典排序输入一行字符串至少20个数字数与数#include<string> #include<iostream> using namespace std; int main() { string ans[1000],load; int i=0; int j=0; while(cin>>ans[i]) { i++; while(ans[i][j]) { if(a...

排序算法c语言n个数字的排序我近期做练习的时候专门为排序做了一个c程序,你看看怎么样,包括了很多排序方法 #include#include#include#define LEN 10 //初始化数组 void init(int *arr,int len); //打印数...