Algo在一个非常大的数组中找到重复项

时间:2015-09-05 03:38:51

标签: javascript java python c algorithm

在一次技术访谈中得到了这个问题。 我知道使用(在java中)HashSet解决这个问题的方法。

但是当面试官强迫“一个非常大的阵列让我们说给定数组中的1000万个元素”时,我无法理解。

我需要改变方法吗?如果没有,那么实现这一目标的效率应该是多少?

PS:Algo或实现与语言无关。

谢谢。

5 个答案:

答案 0 :(得分:4)

你可以在O(nlog(n))中完成:

  • 对数组进行排序
  • 一次性找到重复项(它们将彼此相邻)。

我认为这就是采访者想要听到的内容。

如果您进行了合并排序或快速排序,则可以在隐藏时间合并时找到重复项。 这些可以实施"就地"或" by-part"如果数组太大而无法放入内存中。

答案 1 :(得分:3)

有一些关键的事情,面试官希望你回答:如果你不能在内存中加载数组,那么how much I can load。这些是解决问题的步骤:

  1. 您需要将数组划分为可用的内存量。
  2. 假设您可以一次加载1M号码。您已将数据拆分为k parts。您加载第一个1M并构建它的Min Heap。然后移除顶部并在Min Heap上应用Heapify。
  3. 对数据的其他部分重复相同的操作。
  4. 现在你将有K个分组。
  5. 现在从每个K分组中获取第一个数字,然后再次构建Min Heap
  6. 现在从Min Heap中移除顶部并将值存储在temporary variable中,以便与下一个查找重复项的数字进行比较。
  7. 现在从上次删除其号码的同一个分组(部分)中获取下一个号码。将该数字放在Min Heap之上并应用Heapify。
  8. 现在,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]