问题描述
|
在最近的一次采访中问
有一个包含一百万个整数的日志文件。每个整数的长度为32位。日志文件中的特定整数值可能会重复。您可以顺序读取日志文件。您还可以按顺序读取和写入临时文件。随时可以打开的文件数量没有限制。但是,在任何给定时间,您在内存中最多可以保留2000个整数。
我被要求生成一个直方图,以显示日志文件中出现的每个整数值的绝对计数,并说明每个整数必须加载到内存中的次数的顺序复杂度的上限
解决方法
这是一个令人困惑的问题。您不能只读取2,000个数字,对它们进行排序,然后再写入临时文件吗?进行500次,然后进行N次合并。每个数字将两次加载到内存中。
如果必须在只有2 GB RAM的计算机上对1 TB大小的文件进行排序,则这与您要做的事情相同。
,打开232个临时文件,每个整数一个。顺序读取一次日志文件。每当读取整数n时,请将“ 1”写入临时文件编号n。然后通过遍历所有临时文件来生成直方图。每个整数只能读一次到内存中,因此它是O(n)算法。
,保留在内存中2000 int =大小
缓冲区
读写文件无限制
=每个数字计数将存储在一个文件中。
32位长度数=每个
文件是一个数字,文件名
是代表
整数(可以使用整数值
以及)
显示直方图(表示无顺序
需要)
伪代码:
count = 2000
HashMap<number,number> = new
code:readbuffer
while count != 0
read NextNumber
if HashMap.HasKey NextNumber then HashMap[NextNumber]++
else HashMap[NextNumber]=1
count --;
end while
code:flushbuffer
foreach Key in HashMap
if exists FileName Key.ToBinnary
FileValue += HashMap[HashKey]
else WriteNewFile FileName=Key.toBinnay; SetValue = 1
end foreach
code: histogram
each file name is the number;
each file value is the count.
费用:readbuffer
顺序号读取= 2M(M =百万)
Map.HasKey =(在2000年记录中搜索密钥,最坏的情况是该数字不存在,SUMMARY(∑2000)x2M)
地图上的SetValue与上述费用相同
总计:(2M)+(2Mx∑2000)x2
费用:flushbuffer
File.exists 2M
费用:直方图
2M
总计= 6M + 4Mx∑2000
,实现基于文件的B树。
文件名是GUID。
文件内容为:
看数字
计数
左节点文件
右节点文件
经过一遍之后,复杂度可以从B树得出。
而且您的直方图隐含在结构中。