给定 40 亿个数字,如何找到不在这 40 亿个数字中的数字?我们只有 1GB 的内存 [重复]
Posted
技术标签:
【中文标题】给定 40 亿个数字,如何找到不在这 40 亿个数字中的数字?我们只有 1GB 的内存 [重复]【英文标题】:Given 4 billion numbers, how to find a number which is not in these 4 billion numbers? We have only 1GB of memory [duplicate] 【发布时间】:2011-07-15 11:30:09 【问题描述】:给定 40 亿个数字,如何找到一个不在这 40 亿个数字中的数字?我们只有 1GB 的内存。
数字可以不连续。
如何在 10MB 内存中做同样的事情?
【问题讨论】:
这 40 亿个数字在哪里给出?数据库?一份文件?数组?网络?在哪里 数字是连续的吗?如果数字是连续的,这并不太难,如果不是,那就更难了。 我认为问题的意图是给定的数字在范围内随机分布,例如。我们有 1 到 1000 范围内的 900 个数字。我们如何用 100 个数字的存储量最有效地解决这个问题?以及如何仅用少量存储来解决它。只取一个 max() 可能不会产生答案,因为集合中可能有 1000 个。 @Abius:我想我们可以假设它们在磁盘上,因为我们有 RAM 的限制 @rsbarro: 不,数字绝对不是连续的,否则它是微不足道的 【参考方案1】: 转到http://en.wikipedia.org/wiki/Sorting_algorithm。 选择空间复杂度为1的算法。也许选择一个不起眼的,这样你就可以看起来像一个真正的算法爱好者。如果您想看起来像团队合作者,或者选择每个人都听说过的流行的。 记住伪代码并假装你已经记住了每个排序算法,因为这是你为了好玩在面试中炫耀的。 利润。【讨论】:
【参考方案2】:假设这是一个您只需要运行一次的例程,请使用可用内存量作为限制因素。将数字加载到数组中,直至您可用的内存量。使用您喜欢的排序算法对数组进行排序。进行二分搜索以查看该值是否存在。如果它在那里,你就完成了,如果没有,那么清除数组并开始从你上次离开的文件中加载数字。重复该过程,直到找到匹配项或到达文件末尾。
例如,如果您有 1 GB 的空间可以使用,并且数字是 4 字节大(例如,C# int),则将数组上限设置为 1024 ^ 3 / 4 = 268435456 * i(其中 i 是一些value
如果您只有 10 MB 可用,请将上限数组设置为 1024 ^ 2 * 10 / 4 = 10485760 * i。
实际上,现在我想起来了,因为无论如何排序都必须触及每个值,所以最好只扫描列表并忽略排序。但是,如果您想将列表保存在有序集中(最多为数组的大小)以供以后处理,则排序将很有用。在这种情况下,您还需要存储数组的大小,这样您就可以依赖于它们在每次连续运行时都被排序的事实。
【讨论】:
【参考方案3】:考虑到 OP 问题的广泛性,可以冒险假设其中有 40 亿个随机数,然后选择另一个随机数,需要检查该新数字是否已经在列表中。
如果是这种情况,一个简单的二分搜索(考虑到数字是有序的)应该足以满足 O(logN) 的比较时间。
【讨论】:
我把这个问题读成一个列表中有超过 40 亿个随机数,选择另一个不在列表中的随机数。但你可能是对的。 @jb 如果是这样的话,如果数字是有序的,那就更容易了,只需从第一个到最后一个检查数字之间的差异。当然这是可行的,因为我们都假设我们正在处理自然数字。如果我们冒险研究 REAL 数字,那么事情就会变得非常糟糕,因为在 1 和 2 之间有无限的数字。 要求是内存而不是时间。最坏情况下的空间复杂度是 O(n),就像在 bad malloc 中一样。 @nate,不管怎样,如果我们要讨论内存分配,没有提到数字的大小......它是字节吗? 16?整数32?整数64?如今,多亏了托管语言和操作系统。我们不需要太担心内存分配,因为分页已经为我们完成了。但是,方法仍然存在。搜索 40 亿或 10 的算法是相同的。唯一改变的是向量在内存中的加载方式。我们需要自己分配还是让操作系统来分配?为我们做吗? @nate,OP 的问题太笼统,无法准确回答。数据的大小是多少?处理器是 8 位、16 位、32 位还是 64 位?分页是否为我们完成?首先存储的数字在哪里?在将约束仅放在内存中之前,有很多问题需要回答。【参考方案4】:如果问题是“列表中有 40 亿个随机数,现在选择一个不在列表中的新随机数”。然后我会对列表进行合并排序,使其按 O(n lg n) 的顺序排列。然后遍历列表,以 O(n) 的顺序将当前元素与下一个元素进行比较。比如……
MergeSort(thelist);
for(int i = 0; i < thelist.Length; i++)
if(thelist[i] + 1 == thelist[i+1])
//it's just a duplicate element
continue;
else if (thelist[i] + 1 != thelist[i+1])
Console.WriteLine("the number is 0", thelist[i] + 1);
break;
【讨论】:
【参考方案5】:求这组数的最大值(O(N)在时间,常数空间),不在组内的数是max+1。
这对我来说并不是一个非常具有挑战性的问题。寻找不在集合中的最小自然数可能是一个更好的问题。
【讨论】:
我认为他的意思是集合中可能有 17、4、6、10、15,您如何确定 12 是否不在集合中。【参考方案6】:好吧,假设我可以选择一个大于 40 亿个数字中的最大值的数字:
set i = 0
for each number:
load the number into memory
set i = max(i, number + 1)
【讨论】:
但是如果这 40 亿个数字已经包含了 MAX_VALUE 和 MIN_VALUE,那么我们需要找到小于 MAX_VALUE 和大于 MIN_VALUE 的数字,因为它应该在整数范围内。他们要求“整数”,你怎么看?以上是关于给定 40 亿个数字,如何找到不在这 40 亿个数字中的数字?我们只有 1GB 的内存 [重复]的主要内容,如果未能解决你的问题,请参考以下文章
面试被虐如何只用2GB内存从20亿,40亿,80亿个整数中找到出现次数最多的数?