在 O(n) 和恒定空间中查找重复
Posted
技术标签:
【中文标题】在 O(n) 和恒定空间中查找重复【英文标题】:Find repeating in O(n) and constant space [duplicate] 【发布时间】:2012-02-22 18:17:48 【问题描述】:可能重复:Easy interview question got harder: given numbers 1..100, find the missing number(s)Find the missing and duplicate elements in an array in linear time and constant space
我在一个论坛上看到了一个有趣的问题。
您有 100 个从 1 到 100 的元素,但错误地其中一个数字通过重复自身而与另一个数字重叠。 例如。 1,99,3,...,99,100 数组未排序,如何找到重复的数字?
我知道 Hash 可以做到 O(n) 时间和 O(n) 空间,我需要 O(1) 空间。
【问题讨论】:
为什么你接受了错误的答案? (不是 O(1) 空间) 【参考方案1】:我们可以在 O(n) 和常数空间中做到这一点:
-
对于每个元素,计算
index = Math.abs(a[i]) - 1
检查index
的值
如果是正数,则乘以 -1,即变为负数。
如果是否定的,返回 (index+1
) 作为答案,因为这意味着我们以前见过这个索引。
""
static int findDup(int[] a)
for(int i=0;i<a.length;i++)
int index = Math.abs(a[i]) - 1;
if(a[index] < 0)
return index+1;
else
a[index] = -1 * a[index];
return -1;
【讨论】:
您正在为输入中的每个元素(可能)存储一条信息。这不是恒定的空间。 @Nick 为什么你认为它不是恒定的空间?我使用相同的数组来存储 -ve 符号 @Manan 您仍在使用线性空间来构建您的解决方案。如果您的输入集是不可变的,或者不能随机访问,或者不支持有符号整数,那么您需要自己创建这个数组。 @Manan 问题中没有明确给出这些约束(具有恒定时间随机访问的可修改签名输入),因此假设它们有点牵强。但无论如何,这仍然不符合常数空间算法的条件。这不是 malloc() 需要多少字节的问题;这是你需要记录多少条信息的问题。 @Manana[index] = -1 * a[index];
行覆盖输入。这就是为什么人们说这个解决方案不是恒定空间。【参考方案2】:
计算两个和:总和和平方和。
在你的例子中:
sum = 1+99+3...+100
sq_sum = 1^2+99^2+3^2+...+100^2
假设 y 替换了序列中的 x。
sum = n(n+1)/2 -y+x.
sq_sum = n(n+1)(2n+1)/6 -x^2 +y^2
现在,求解 x 和 y。
恒定空间和 O(n) 时间。
如何求解 x 和 y
>从方程:
x = sum - n(n+1)/2 +y
将其代入第二个等式:
sq_sum = n(n+1)(2n+1)/6 -(sum - n(n+1)/2 +y)^2 +y^2
请注意,y^2 取消,您将得到一个只有一个未知数的线性方程:y。解决它!
【讨论】:
这个答案有 2 票反对票,没有 cmets。请在此处解释不正确之处,以便 OP 可以反驳或修改,并让其他人了解(潜在)问题。 你如何为 x&y 解决这个问题? 确实需要平方和,如果数组长度为 101 并且有 100 个唯一值,那么您将这 100 个唯一值相加得到 5050,假设总和返回为 5149,您立即知道99 被重复,当有多个重复但问题只提到一个值重复一次时,这不起作用。 @Seph 数组长度为100,一个数字重复,一个数字省略。因此有两个未知数,需要两个方程。 为什么有人会对正确答案投反对票?【参考方案3】:新方法。让m
是缺失的数字,r
是重复的数字。通过数组一次,让X
成为XOR
数组条目连同索引1
到n
的结果。然后X = m XOR r
。特别是,它不是0
。让b
是X
的任何非零位(您只需要选择一个,并且存在一个,因为X
不是0
)。通过数组,让Y
成为XOR
数组条目和索引1
到n
的结果,其中位b
是0
并让Z
成为结果的XOR
ing 数组的条目和索引1
到n
其中位b
是1
。然后Y
和Z
持有m
和r
,所以剩下的就是做最后一个pass,看看哪个在数组中。
总空间:4 个(如果您将 X
重复用于 b
,则为 3 个)
总时间:7 次通过(如果您同时对数组执行索引并同时计算 Y
和 Z
,则为 3 次。
因此O(1)
空间和O(n)
时间。
【讨论】:
你确定吗?第一步慢是n+1。所以 array[slow] 返回错误或垃圾,不是吗? 我仍然认为它行不通。考虑有多个周期的情况。或者考虑一个数组[n]=n的情况。 所以对于 X 的每个非零位,您都需要一个额外的通道,对吧?在那种情况下,您的解决方案 O(nlogn) 及时。我不太确定这个事实,但请告诉我。 @ElKamina 不,你只为你最喜欢的非零位做一次。您不必对每个非零位都执行此操作。它适用于任何非零位。 X 的大小是否取决于 n?如果是,那么它不是 O(1) 空间。【参考方案4】:计算所有整数的总和 计算 int p = sum % 100 100 - p 就是答案
【讨论】:
这只会让您区分丢失的号码和重复的号码,但不足以识别其中任何一个。你有两个未知数,你需要方程。请参阅上面 ElKamina 的回答。 这是不正确的。采取两种情况:5 被 10 替换,6 被 11 替换。在这两种情况下,总和将是相同的。 示例 1,99,3,4...100。现在 sum % 100 将是 98。100-98 是 2 :) @topcoder 我得到 1+99+3+4+...+100 % 100 = 47。 @NickBarnes 1 到 100 模 100 的总和不是 0。为什么大家都认为它是? 1+2+...+100 = 5050!!以上是关于在 O(n) 和恒定空间中查找重复的主要内容,如果未能解决你的问题,请参考以下文章
在 O(1) 空间中的数组中查找重复元素(数字不在任何范围内)
287 Find the Duplicate Number 寻找重复数