如何以最小的复杂性识别数组中的重复数字?
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]
,所以交换位置0
和4
。现在,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】:对数组进行排序,然后遍历,直到连续命中两个相同的数字。
【讨论】:
以上是关于如何以最小的复杂性识别数组中的重复数字?的主要内容,如果未能解决你的问题,请参考以下文章
用最小的空间复杂度找出一个长度为n的数组且数据中的元素是[0,n-1]中任一个重复的数据。