从3个数组中查找唯一的公共元素

时间:2010-03-10 15:52:42

标签: algorithm

原始问题:
我有3个盒子,每个盒子包含200个硬币,因为只有一个人从所有三个盒子中拨打电话,因此每个盒子里有一个硬币有相同的指纹,所有硬币的其余部分都有不同的指纹。您必须找到所有3个盒子中包含相同指纹的硬币。这样我们就可以找到从所有3个方框中拨打电话的人的指纹。

转换问题:
你有3个数组,每个数组包含200个整数。鉴于这3个数组中只有一个共同元素。找到共同的元素 请考虑解决此问题,除了平凡的O(1)空间和O(n ^ 3)时间。

7 个答案:

答案 0 :(得分:5)

如果您首先对所有数组进行排序O(n log n),那么在O(n ^ 3)时间内找到公共元素将非常容易。例如,您可以在对它们进行排序后使用二进制搜索。

答案 1 :(得分:5)

Pelkonen答案的一些改进:
从转换后的问题OP:

“鉴于这3个数组中只有一个共同元素。”

我们只需要排序2个数组并找到共同的元素。

答案 2 :(得分:3)

设N = 200,k = 3,

  1. 创建容量≥Nk的哈希表H.

  2. 对于数组1中的每个元素X,将H [X]设置为1.

  3. 对于数组2中的每个元素Y,如果Y在H 中且 H [Y] == 1,则设置H [Y] = 2。

  4. 对于数组3中的每个元素Z,如果Z在H 中且 H [Z] == 2,则返回Z。

  5. throw new InvalidDataGivenByInterviewerException();

  6. O(Nk)时间,O(Nk)空间复杂度。

答案 3 :(得分:2)

对每个整数使用哈希表并对条目进行编码,以便知道它来自哪个数组 - 然后检查具有来自所有3个数组的条目的插槽。 O(n)的

答案 4 :(得分:2)

使用哈希表映射对象来计算频率。迭代所有三个列表,在哈希表中递增出现次数,直到遇到出现次数为3的那个。这是O(n),因为不需要排序。 Python中的示例:

def find_duplicates(*lists):
  num_lists = len(lists)
  counts = {}
  for l in lists:
    for i in l:
      counts[i] = counts.get(i, 0) + 1
      if counts[i] == num_lists:
        return i

或等效,使用集合:

def find_duplicates(*lists):
  intersection = set(lists[0])
  for l in lists[1:]:
    intersection = intersection.intersect(set(l))
  return intersection.pop()

答案 5 :(得分:1)

O(N)解决方案:使用哈希表。 H [i] =映射到i的三个数组中的所有整数的列表。

对于所有H [i]> 1检查其中三个值是否相同。如果是,您有解决方案。您可以使用天真的解决方案进行检查,它应该仍然非常快,或者您可以对那些H [i]进行排序然后它变得微不足道。

如果你的数字相对较小,你可以使用H [i] = k,如果我在三个数组中出现k次,则解决方案是i,其中H [i] = 3.如果你的数字很大,但是使用哈希表。

即使您可以拥有仅对两个数组通用的元素,并且您可以在其中一个数组中包含重复元素的元素,也可以将其扩展为有效。它变得有点复杂,但你应该能够自己解决它。

答案 6 :(得分:1)

如果你想要最快的答案:

  • 排序一个数组 - 时间是N log N。
  • 对于第二个数组中的每个元素,搜索第一个元素。如果找到它,请将1添加到伴随阵列;否则添加0 - 时间是N log N,使用N空格。
  • 对于每个非零计数,将相应的条目复制到临时数组中,压缩它以使其仍然排序 - 时间为N.
  • 对于第三个数组中的每个元素,搜索临时数组;当你找到一个打击,停止。时间小于N log N。

Scala中的代码说明了这一点:

import java.util.Arrays

val a = Array(1,5,2,3,14,1,7)
val b = Array(3,9,14,4,2,2,4)
val c = Array(1,9,11,6,8,3,1)

Arrays.sort(a)
val count = new Array[Int](a.length)
for (i <- 0 until b.length) {
  val j =Arrays.binarySearch(a,b(i))
  if (j >= 0) count(j) += 1
}
var n = 0
for (i <- 0 until count.length) if (count(i)>0) { count(n) = a(i); n+= 1 }
for (i <- 0 until c.length) {
  if (Arrays.binarySearch(count,0,n,c(i))>=0) println(c(i))
}

稍微复杂一点,您可以不使用额外的空间,但代价是对原始阵列的破坏性更大,或者您可以避免以另外N个空间为代价来触摸原始阵列。


编辑:*正如评论所指出的,对于非反常输入,哈希表更快。这是“最快的最坏情况”。最坏的情况可能不是那么不可能,除非你使用一个非常好的哈希算法,这可能会比你的排序花费更多的时间。例如,如果将所有值乘以2 ^ 16,则平均散列(即仅使用位掩码整数作为索引)将在每次短于64k的列表上发生冲突....