找到重复的元素

时间:2010-10-05 15:22:21

标签: algorithm

在一个整数介于1和1,000,000之间的数组中,或者说一些非常大的值,如果单个值出现两次两次。你如何确定哪一个?

我认为我们可以使用位图来标记元素,然后再次遍历allover以找出重复的元素。但是,我认为这是一个高度复杂的过程。有没有更好的方法?

4 个答案:

答案 0 :(得分:2)

这听起来像是家庭作业或面试问题......所以不是泄露答案,而是提示。

  

您可以对可以提前确定答案的一系列整数进行哪些计算?

一旦你意识到这个问题的答案,你应该能够弄明白......如果你仍然无法弄明白......(而且这不是作业)我会发布解决方案:)< / p>

编辑:好的。所以这是优雅的解决方案......如果列表包含范围内的所有整数。

我们知道列表中必须存在1到N之间的所有值。使用Guass' formula,我们可以快速计算一系列整数的期望值:

Sum(1..N) = 1/2 * (1 + N) * Count(1..N).

由于我们知道预期的总和,我们所要做的就是循环遍历所有值并将它们的值相加。该和与预期和之间的差异是重复值。

编辑:正如其他人所评论的那样,问题并未说明范围包含所有整数 ...在这种情况下,您必须决定是否要优化记忆或时间。

如果要使用O(1)存储执行操作,可以执行列表的就地排序。在排序时,您必须检查相邻的元素。一旦你看到重复,你知道你可以停止。最佳排序是平均O(n log n)操作 - 它建立了以这种方式查找副本的上限。

如果要优化速度,可以使用额外的O(n)存储。使用HashSet(或类似结构),从列表中插入值,直到确定要将副本插入HashSet。将n个项插入HashSet是一个平均的O(n)操作,它将该项设置为此方法的上限。

答案 1 :(得分:0)

您可以尝试将位用作hashmap:

位置k处的

1表示在

之前出现数字k 位置k处的

0表示在

之前没有出现数字k

伪代码:

0. assume that your array is A
1. initialize bitarray(there is nice class in c# for this) of 1000000 length filled with zeros
2. for each num in A:
   if bitarray[num] 
      return num
   else
      bitarray[num] = 1
   end

答案 2 :(得分:0)

位图解决方案的时间复杂度是O(n),看起来你不能做得更好。但是,对于通用的数字列表,它将占用大量内存。对数字进行排序是检测重复项的一种明显方法,如果您不介意当前的订单更改,则不需要额外的空间。

答案 3 :(得分:0)

假设阵列的长度n

假设我使问题更容易,我向你保证重复的元素在数组中,第一个元素在前n / 2个元素中,第二个元素在最后的n / 2个元素中。现在我们可以想到玩一个游戏,其中两个人各自拥有一串n / 2个元素,并想知道他们必须发送多少个消息以确保它们的元素都不相同。由于第一个玩家可以模拟任何通过数组传递的算法的运行,并将其内存的内容发送给第二个玩家,因此他们需要发送的消息数量的下限意味着内存的下限任何算法的要求。

但是在这个简单的游戏中很容易看出他们需要发送n / 2条消息以确保它们不会持有任何相同的元素,从而产生下限。

编辑:这概括表明,对于使k通过数组并使用存储器m的算法,m * k = Omega(n)。事实上很容易看出你可以用这种方式将记忆换掉。

当然,如果您愿意使用不仅仅通过数组的算法,您可以按照建议做得更好:对数组进行排序,然后进行1次传递。这需要时间O(nlogn)和空间O(1)。但奇怪的是,这证明了任何只通过数组的排序算法必须花费时间Omega(n ^ 2)!打破n ^ 2界限的排序算法必须进行随机访问。