Javascript 在非常大的数组中查找重复项的算法
在一次技术面试中,我得到了这个问题。 我知道使用(java)哈希集解决这个问题的方法 但当采访者强行说出“一个非常大的数组,比如说给定数组中有1000万个元素”这个词时,我无法理解 我需要改变方法吗?如果没有,实现这一目标的效率应该是什么 PS:Algo或实现与语言无关 谢谢。你可以用O(nlog(n))来做:Javascript 在非常大的数组中查找重复项的算法,javascript,java,python,c,algorithm,Javascript,Java,Python,C,Algorithm,在一次技术面试中,我得到了这个问题。 我知道使用(java)哈希集解决这个问题的方法 但当采访者强行说出“一个非常大的数组,比如说给定数组中有1000万个元素”这个词时,我无法理解 我需要改变方法吗?如果没有,实现这一目标的效率应该是什么 PS:Algo或实现与语言无关 谢谢。你可以用O(nlog(n))来做: 对数组进行排序 在一次传递中找到重复项(它们将彼此相邻) 我想这就是面试官想听到的 如果您进行了合并排序或快速排序,则可以在隐藏时间合并时查找重复项。 这些可以“就地”实现,如果数组
- 对数组进行排序
- 在一次传递中找到重复项(它们将彼此相邻)
这些可以“就地”实现,如果数组太大而无法装入内存,则可以“部分”实现。有一些关键问题,面试官希望你回过头来问:如果你无法在内存中加载数组,那么
我可以加载多少
。以下是解决问题的步骤:
k个部分
。您加载第一个1M并构建它的Min Heap
。然后移除顶部并在Min Heap
上应用HeapifyMin堆
Min堆中移除顶部
,并将该值存储在临时变量
中,以及用于与下一个数字进行比较以查找重复项Min Heap
的顶部,然后应用HeapifyMin堆的顶部是下一个排序的数字,并将其与临时变量进行比较以查找重复项。如果数字不重复,则更新
临时变量
简而言之,您必须从数组中找出所有唯一的元素 所以您可以创建一个对象,并将数组中的每个元素添加为对象的属性
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;
}
需要记住的一点是,O表示法不一定告诉您什么算法最快。如果一个算法是O(n logn),另一个算法是O(n2),那么有一些值M,使得第一个算法对于所有n>M都更快。但是M可能比您必须处理的数据量大得多 我之所以提出这个问题,是因为我认为
HashSet
可能仍然是最好的答案,尽管我必须分析它才能确定答案。假设不允许您设置一个包含1000万个存储桶的哈希表,那么您仍然可以设置一个大小合理的表。假设您可以创建一个表大小为100000的HashSet
。然后,这些桶将是一组对象。如果n是数组的大小,则平均存储桶大小将为n/100000。因此,要查看元素是否已在哈希集中,如果不在,则添加它,将需要固定的时间来计算哈希值,如果元素存储在线性列表(*)中,则需要O(n)来搜索bucket中的元素。从技术上讲,这意味着查找所有重复项的算法是O(n2)。但是,由于n2中的一个n用于比数组大小小得多的线性列表(100000倍),因此在我看来,对于1000万个项目,它仍然比O(n log n)排序花费的时间要少得多。M的值,即O(n logn)排序变得更快的点,很可能比这个值大很多。(不过,我只是在猜测;要确定这一点,需要进行一些分析。)
无论如何,我倾向于反对使用排序,因为如果您只需要查找重复项,那么排序所做的工作比您需要的要多。您不需要将元素按顺序排列,只需查找重复项即可。这对我来说意味着排序不太可能是最好的答案
(*)注意,在Java8中,每个bucket中的元素将位于某种搜索树(可能是红黑树)中,而不是线性列表中。因此,算法仍然是O(n log n),并且可能比排序快得多。因此,假设非常大的数组可以放入内存,但只留下很少的额外内存(即与数组大小类似的另一个数据结构),然后根据一些假设,您可以在O(n)中执行此操作没有额外内存的时间和位置。
假设1:数组中的所有值:0当您找到它们时,您必须删除重复的值还是必须打印它们?他所说的“非常大的数组”(假设给定数组中有1000万个元素)的意思是,您无法将它们保存在内存中。在Python中,可以使用集合。计数器无需算法:从集合导入计数器;c=Counter()
所有大于1的计数都是重复的。@Joe,采访者的陈述是“在大数组中查找重复的整数”。他想要的是,找到所有的副本和出现的次数。我认为,保持索引值可能会有更大的帮助。面试是为了衡量你解决问题的能力,看看你是否知道自己在说什么。他们可能一直在寻找基于磁盘的解决方案。只需问一些关于这个问题的问题。数据的大小大于您可用的内存大小。合并排序再次需要相同大小的额外内存,因此合并排序不是答案。假设对象是可排序的,而不是仅定义相等。如果对象是可散列的,那么你可以通过创建一个散列映射或字典在一次过程中完成这项工作。是的,安普安,b
>>> 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]