一、用4字节表示的整数个数为23240亿,而用2字节表示的无符号整数个数为2166万。 二、2G231B20亿字节。 三、要找出出现次数最多的数,则应记录每个数出现的次数,最快的方法是在内存中将每个数出现的次数记录下来,记录的方法则是内存地址对应数,相应地址的内存单元记录次数,但2G内存以字节为单位仅能记录20亿个数,且每个数出现的次数大于255将会出现溢出风险。因此,这一方案不可取。 四、这样只能将每个次出现的次数记录在磁盘上。这样在磁盘上建一个16G的文件,每4字节对应一个整数,可对应40亿个整数,并用于记录相应整数的出现的次数。 1、将文件初始化。 2、依次读取数据,并用无符号整数记录在磁盘文件中,如出现溢出,则该数为次数最多的数。 3、从文件中读取各数出现的次数,用一个变量A记录最高次数,再用一个变量B记录最高次数出现的数据个数,要用个文件依次记录最高次数出现的数。当最高次数增加时,A1,B置1,文件中写入该数,同次数的数出现时,B1,文件相应位置写入该数,直到全部读完。 这样根本不需2G内存。 需求: 使用2G的内存,找出80亿个数字中出现最多的数字。 假设: 整数为4字节(2324G),即最大40多亿。 所有的数字有80亿个。所有数字在硬盘中,本身不会占用内存。 所用内存为2G多一些,例如有限的变量。但多出的内存和2G相比可以忽略不计。 设计:80亿的计数可以用4字节保存(2324G)。因为如果计数超过一半,则表明该数字一定是出现最多的。 2G的内存约可以保存5亿多数字的计数(2G4512M)。 也就是说,将2G的内存分成单位为4字节的数组,可以一次获得05亿多之间出现最多的数字。 步骤:顺序扫描80亿个数字,忽略0512M之外的数字,每个数字N的出现个数累加存放在第N个数组元素中。最后将最出现最多的数字及其次数保存起来,出现并列第一时,只保存第一个数字。如果过程中某数字出现个数超过40亿,则直接结束。 再次扫描所有数字,此次忽略512M1G之外的数字。每个数字N的出现个数累加存放在第N512M个数组元素中。本轮所获得的数字的出现个数和第一轮结果比较,保存较大的那个。 由于整数取值范围为4G,所以最多扫描8次后即可获得最终结果。 问题: 如果整数长度为8字节,则需要扫描约300多亿次(264512M240)。所以此算法并不适用于8字节的整数。 讨论: 当数字足够多,且数字取值范围足够大时,以有限内存获取出现次数最多的数字几乎是不可能的。因为数字的取值范围极大,且数字极多,任何哈希或其它分片的算法都有可能出现极端情况,导致分片数据过多而无法一次性导入内存计算。除非我们预先知道部分数字规律,否则考虑到效率,应该只会要求得到近似结果。 2g内存不是重点,80亿数字和取值范围才是重要的: 1。80亿的数字至少需要加载一遍,才知道有哪些数据 2。如果是取mapsize216或者80亿开方,一个mapint,int大mapsize的空间不到1m 3。顺序读80亿数据,除以mapsize取余,同一余数放追加同一文件,余数作文件名 4。顺序读取步骤3产生的所有文件,读取的每个文件时新建mapsize大小的hashmap,统计每个数的次数,再取该hashmap中出现最多次数的整数放到新的map中 5。依次读完步骤3产生的文件,就能得到每个文件最多次数的整数map 所有步骤需要80亿数据的两次读盘,一次写盘,mapsize次取最大值,80亿数据取余数 只有不是程序员才会出这样的题,你要知道,3、8、55246546是整数,但12345的阶乘,葛立恒数等也是整数,葛立恒数的葛立恒数次方也是整数,你没有限定整数范围,所以我觉得真正的程序员会先和你谈需求。另,我就是程序员。 64mb内存就够。假设你的数据都存在文件中。 1,分治法,空间换时间,分片读取hash到n个文件中 2,统计每个文件中出现次数最多的数字 3,堆排序,对比每个文件中出现次数最多的数字。 4,结束 2G只能放5亿个整数。 先建个数组: intnum〔5亿〕; 分页处理数字,每页5亿个。 第一次遍历数字 if(数字0数字5亿) num〔数字〕 记录次数最多的数和已处理的数的总数 第二次遍历数字 if(数字5亿数字10亿) num〔数字5亿〕 记录次数最多的数和已处理的数的总数 依次循环处理完所有的数字。就得到结果。 如果数字集允许删除,每处理一页就删掉已处理的数,效率就要高得多了。 程序只涉及到逻辑运算和加法,速度是最快的。 把数字变成字符串处理 定义一个结构是a,数字,次数 建立动态数组,数组元素类型为结构a 初始数据有两个0和最大数。升序。 读取一块数据 扫描数据块,对每一个数字在数组中执行比较 对当前数字在数组中插入排序,如果没找到,比上一个数字小,比下一个数字大,插入这个数字,其次数为1 如果找到,其次数加一 读取下一块 没要求时间,也就不用说优化了。 只需要考察这个数组占用空间大小。 假定是4字节整数,20亿数字需要80亿字节。2G内存是20亿字节,显然全部在内存运行是不够的。 把数组延伸到外存是必要的。 由于数组是有序的,显然可以分块。我们可以把数组分成16,32,64等块数。 算法核心是插入排序。 如果追求更高效率,可以选择归并排序。相当于对原数据先进行分块排序再合并,合并时重复数据压缩为一个数据和出现次数。 因为有外存,操作系统会提供虚拟内存,理论上不用考虑2G内存问题。 这里提出2G内存限制,无非是把原数据划分为多少块来做的问题,可归结为分治算法。 这是一个wordcount取max的计算根据mapreduce思路先将待统计的数据集分区让相同的数字分到同一个分区分区内进行groupbycount后取max的一条再与其它分区的max结果两两比较保留较大的一条最终结果就是全部数据里出现次数最大的一条