在数组中找到一个非重复元素?

时间:2012-04-20 04:56:02

标签: arrays algorithm time-complexity

我有一个n元素数组,其中只有一个元素不重复,否则所有其他数字重复> 1次。并且对数组中的数字范围没有限制。

有些解决方案是:

  • 使用哈希但这会导致线性时间复杂度,但空间复杂度非常差
  • 使用MergeSort O(nlogn)对列表进行排序,然后找到不重复的元素

有更好的解决方案吗?

3 个答案:

答案 0 :(得分:1)

一种通用的方法是实现一种bucketing技术(其中散列是一种技术),使用它们的标识(比如索引)将元素分配到不同的“桶”中,然后找到最小尺寸的桶(在你的1中)案件)。我认为,这个问题也被称为少数民族问题。存储区中将存在与您的集合中的唯一元素一样多的存储桶。

通过散列执行此操作是有问题的,因为冲突以及您的算法可能如何处理。某些关联数组方法(如尝试和可扩展哈希)似乎不适用,因为它们更适合字符串。

以上的一个应用是Union-Find data structure。您的集合将是存储桶,您需要为数组中的每个元素调用MakeSet()和Find(),每次调用的成本为$ O(\ alpha(n))$,其中$ \ alpha(n) $是极其缓慢增长的逆Ackermann函数。你可以认为它实际上是一个常数。

当元素已经存在时,你必须做联盟。通过一些更改来跟踪具有最小基数的集合,此解决方案应该可行。此解决方案的时间复杂度为$ O(n \ alpha(n))$。

您的问题似乎与Element Uniqueness problem松散相关。

答案 1 :(得分:1)

如果您有严格的空间限制,请尝试多次扫描。

假设输入有n个元素,你只能在你的记忆中容纳m个元素。如果您使用哈希表方法,在最坏的情况下,您需要处理n / 2个唯一数字,因此您需要m> n / 2。如果你没有那么大的m,你可以将n个元素分成k =(max(输入) - min(输入))/(2m)组,然后继续扫描n个输入元素k次(最差的)案例):

第一次运行:你只需要hash-get / put / mark /任何值为<分钟(输入)+ M * 2;因为在范围(min(输入),min(输入)+ m * 2)中,最多有m个唯一元素,你可以处理它。如果你很幸运,你已经找到了独一无二的,否则继续。

第二次运行:仅对值范围内的元素(min(输入)+ m * 2,min(输入)+ m * 4)进行操作,并且 等等,等等

通过这种方式,您可以将时间复杂度降低到O(kn),但是您得到的空间复杂度为O(m)

答案 2 :(得分:1)

我想到了两个想法:

  • 对于你的需求,smoothsort可能是比引用的mergesort更好的选择,因为它在内存使用中是O(1),在最坏的情况下是O(nlogn)作为合并排序但是O(n) )在最好的情况下;

  • 根据splay tree的(反向)想法,你可以制作一种树 使用后将叶子推向底部(而不是像展开树一样向上)。这仍然会给你一个O(nlogn)种类的植入,但优点是找到唯一元素的O(1)步骤,它将是根。排序算法是O(nlogn)+ O(n)的总和,该算法为O(nlogn)+ O(1)

否则,正如您所说,使用基于散列的解决方案(如散列实现的集合)将导致O(n)算法(O(n)插入并向其添加计数引用和O(n)到遍历你的设置以找到唯一元素)但你似乎不喜欢内存使用,虽然我不知道为什么。记忆很便宜,这些天......