在一次技术访谈中得到了这个问题。 我知道使用(在java中)HashSet解决这个问题的方法。
但是当面试官强迫“一个非常大的阵列让我们说给定数组中的1000万个元素”时,我无法理解。
我需要改变方法吗?如果没有,那么实现这一目标的效率应该是多少?
PS:Algo或实现与语言无关。谢谢。
答案 0 :(得分:4)
你可以在O(nlog(n))中完成:
我认为这就是采访者想要听到的内容。
如果您进行了合并排序或快速排序,则可以在隐藏时间合并时找到重复项。 这些可以实施"就地"或" by-part"如果数组太大而无法放入内存中。
答案 1 :(得分:3)
有一些关键的事情,面试官希望你回答:如果你不能在内存中加载数组,那么how much I can load
。这些是解决问题的步骤:
k parts
。您加载第一个1M并构建它的Min Heap
。然后移除顶部并在Min Heap
上应用Heapify。Min Heap
。Min Heap
中移除顶部并将值存储在temporary variable
中,以便与下一个查找重复项的数字进行比较。Min Heap
之上并应用Heapify。Min Heap
的顶部是您的下一个已排序的数字,如果数字不重复,则将其与temporary variable for finding the duplicates. Update the
临时变量进行比较。答案 2 :(得分:3)
要记住的一点是,O符号并不一定能告诉您哪种算法最快。如果一个算法是O(n log n)而另一个算法是O(n 2 ),则有一些值 M ,这样对于所有n> 1,第一算法更快。 中号。但 M 可能会比您需要处理的数据量大得多。
我提出这个问题的原因是我认为HashSet
可能仍然是最好的答案,尽管我必须对其进行剖析才能确定。假设您不允许设置包含1000万个桶的哈希表,您仍然可以设置合理大小的表。假设您可以创建一个表大小为100,000的HashSet
。然后桶将是一组对象。如果 n 是数组的大小,则平均存储区大小将为 n / 100000.因此要查看某个元素是否已在HashSet
中,并且如果没有,则添加它,将花费一定的时间来计算哈希值,如果它们存储在线性列表(*)中,则需要O( n )来搜索桶中的元素。从技术上讲,这意味着找到所有重复项的算法是O( n 2 )。但是,因为 n 2 中的 n 之一是针对比数组大小小得多的线性列表(通过因子)对于1000万件物品来说,似乎我可能比O( n log n )排序花费的时间少得多。 M 的值,即O( n log n )排序变得更快的点,可能远远大于那。 (我只是在猜测;要确定某些情况需要进行一些分析。)
无论如何,我倾向于反对使用排序,因为如果您需要做的就是找到重复项,那么排序会比您需要做更多的工作。您不需要按顺序放置元素,只是为了查找重复项。对我来说这表明排序不太可能是最好的答案。
(*)请注意,在Java 8中,每个存储桶中的元素将位于某种搜索树中,可能是红黑树,而不是线性列表。所以算法仍然是O( n log n ),并且仍然可能比排序快很多。
答案 3 :(得分:1)
简而言之,你必须找出数组
中的所有独特元素因此,您可以创建一个对象,并将数组中的每个元素添加为对象的属性。
function uniqueArray(arr){
var length = arr. length,
uniqueElementArray = [];
while(length >= 0){
obj [arr[length]] = true;
length-- ;
}
for(var i in obj){
uniqueElementArray.push[i];
}
return uniqueElementArray;
}
答案 4 :(得分:0)
所以假设非常大的数组可以适应内存但是留下很少的附加内存(即与数组大小相似的另一个数据结构),然后通过一些假设你可以在O(n)时间和没有额外记忆的地方
假设1:数组中的所有值:0< = value<阵列长度(10,000,000)
假设2:您可以修改数组
>>> arr = [3, 1, 3, 5, 4, 3, 4, 2, 1]
>>> for i, v in enumerate(arr):
>>> while arr[v] != arr[i]:
>>> arr[i], arr[v] = arr[v], arr[i]
>>> v = arr[i]
>>> arr
[3, 1, 2, 3, 4, 5, 4, 3, 1]
重复项位于值不等于索引的位置。
>>> [v for i, v in enumerate(arr) if i != v]
[3, 4, 3, 1]