如何以最小的复杂性识别数组中的重复数字?

Posted

技术标签:

【中文标题】如何以最小的复杂性识别数组中的重复数字?【英文标题】:How to identify the duplicated number, in an array, with minimum compexity? 【发布时间】:2011-08-11 08:45:11 【问题描述】:

有一个大小为 10,000 的数组。它以随机顺序存储数字 1 到 10,000。 每个数字只出现一次。

现在,如果从该数组中删除任何数字,并且将任何其他数字复制到数组中。

我们如何以最小的复杂性识别哪个数字是重复的?

注意:我们不能使用另一个数组。

【问题讨论】:

How to find a duplicate element in an array of shuffled consecutive integers? 的可能重复项 @Pavel:这个问题不同,因为在这个问题中,一个数字也被删除了。那里的解决方案在这里不起作用。 @Potato,好吧,你是对的,我错了。 【参考方案1】:

最快的方法是 O(N) 就地鸽巢排序。

从数组的第一个位置a[0] 开始。假设它的值为5。你知道5 属于a[4],所以交换位置04。现在,a[0] 中有一个新值。把它换到它需要去的地方。

重复直到a[0] == 1,然后转到a[1]并交换直到a[1] == 2,等等。

如果您最终尝试交换两个相同的值,那么您已经找到了重复值!

运行时间:O(N),系数非常低,提前退出。所需存储空间:零。

奖励优化:计算发生了多少交换,如果n_swaps == array_size 则提前退出。当我实现 a similar algorithm 来排列序列时,这导致了 15% 的改进。

【讨论】:

【参考方案2】:

计算元素的总和和平方和(平方和需要 64 位值)。从这些您可以恢复修改了哪个元素:

减去未修改数组的预期值。 如果 x 被删除并且 y 重复,则总和的差为 y - x,总和的差为 y2 - x2 = (y + x) (y - x)平方和。 从中很容易恢复 x 和 y。

编辑:请注意,这可能比鸽巢排序更快,因为它在数组上线性运行,因此对缓存更友好。

【讨论】:

【参考方案3】:

为什么不简单地使用第二个数组或其他数据结构,如哈希表(如果您愿意,可以使用哈希表,取决于内存/性能权衡)。第二个数组将简单地将数字的计数存储在原始数组中。现在只需在原始数组的访问函数中添加一个 +/- 即可立即获得信息。

ps 当你写“我们不能使用另一个数组”时——我假设你不能改变 ORIGINAL 数据结构。然而,使用额外的数据结构是可能的......

【讨论】:

【参考方案4】:

对数组进行排序,然后遍历,直到连续命中两个相同的数字。

【讨论】:

以上是关于如何以最小的复杂性识别数组中的重复数字?的主要内容,如果未能解决你的问题,请参考以下文章

面试宝典-面试题3.1:数组中的重复数字

用最小的空间复杂度找出一个长度为n的数组且数据中的元素是[0,n-1]中任一个重复的数据。

以下算法在未排序数组中找到最小值的复杂性

如何从数组中的数字中找到最大和最小数字[重复]

Leetcode快速入门之第七节课: 节省时空复杂度的巧妙技巧

剑指offer 03.数组中重复的数字