在N个数组中查找公共元素

时间:2010-05-28 22:51:55

标签: algorithm

如果我有N个数组,那么找到共同元素的最佳方法是什么(时间复杂度。空间并不重要)。你可以找到1个元素并停止。

编辑:元素都是数字。

编辑:这些都是未分类的。请不要排序和扫描。

这不是作业问题。很久以前有人问我这个问题。他正在使用哈希来解决问题并问我是否有更好的方法。

5 个答案:

答案 0 :(得分:4)

创建哈希索引,将元素作为键,计为值。遍历所有值并更新索引中的计数。然后,遍历索引并检查哪些元素有count = N.查找索引中的元素应该是O(1),并且循环遍历所有M个元素应该是O(M)。

如果要保持特定于某个输入数组的顺序,请循环该数组并按该顺序测试索引中的元素计数。

一些特殊情况:

如果你知道元素是(正)整数,且最大数量不是太高,你可以使用普通数组作为“哈希”索引来保持计数,其中数字只是数组索引。 / p>

我假设在每个数组中每个数字只出现一次。适应更多事件应该很容易(设置第i个数组的计数中的第i位,或者只在当前元素计数== i-1时更新)。

编辑当我回答这个问题时,这个问题没有“更好的方式”而不是哈希。

答案 1 :(得分:0)

最直接的方法是将前两个数组相交,然后将此交集与剩余的N-2数组相交。

如果未使用您正在使用的语言定义“交叉点”,或者您需要更具体的答案(即您需要“如何进行交叉”的答案),请修改您的问题。< / p>

没有排序,根据给定的信息,没有一种优化的方法可以做到这一点。 (即,相对于彼此对所有元素进行排序和定位,然后迭代数组的长度,同时检查所有数组中的已定义元素)

答案 2 :(得分:0)

问题是有比哈希更好的方法。没有比做散列更好的方法(即更好的时间复杂度),因为散列每个元素的时间通常是恒定的。经验表现也是有利的,特别是如果值的范围可以一对一地映射到维持计数的数组。然后,时间与所有阵列中的元素数量成比例。排序不会提供更好的复杂性,因为这仍然需要至少访问每个元素一次,然后有用于对每个数组进行排序的日志N.

回到散列,从性能的角度来看,通过不完全处理每个数组,您将获得最佳的经验性能,但在继续进入下一个数组之前,只处理每个数组中的一个元素块。这将利用CPU缓存。当公共元素出现在数组的相同区域时(例如,所有数组开头的公共元素),它也会导致更少的元素被散列在有利的情况下。最坏情况下的行为并不比完全散列每个数组更糟糕 - 仅仅是元素被散列。

答案 3 :(得分:0)

我认为catchmeifyoutry建议的方法无效。

我们假设您有两个阵列 1:{1,1,2,3,4,5} 2:{1,3,6,7}

然后答案应该是1和3.但是如果我们使用哈希表方法,1将有计数3,我们永远不会找到1,在他的情况下。

如果输入这样的内容,问题也变得更加复杂: 1:{1,1,1,2,3,4} 2:{1,1,5,6}

我认为我们应该将输出设为1,1。在这两种情况下,建议的方法都失败了。

解决方案:

读取第一个数组并放入哈希表。如果我们再次找到相同的密钥,请不要增加计数器。以相同的方式读取第二个数组。现在在散列表中,我们有常见的元素,计为2。

但是这种方法在我之前给出的第二个输入集中也会失败。

答案 4 :(得分:-1)

我首先从退化情况开始,找到2个数组之间的共同元素(稍后会详细介绍)。从那里我将有一个常见值的集合,我将其用作数组本身并将其与下一个数组进行比较。此检查将执行N-1次或直到“进位”公共元素数组降至0。

我可以想象,通过分而治之,将N个阵列分割成树的末端节点,可以加快速度。树的下一级是N / 2个公共元素数组,依此类推,直到你在顶部有一个填充或不填充的数组。在任何一种情况下,你都有答案。

如果没有排序和扫描最佳操作速度,您可以比较2个公共元素的数组是O(N 2 )。