所以我的代码如下所示。输入是一个列表,其中只有一个重复项和一个缺失项。答案是两个元素的列表,其中第一个是列表中的重复元素,第二个是列表中缺少的元素,范围是1到n。 示例= [1,4,2,5,1]答案= [1,3] 以下代码有效。
是的,我错误地认为复杂性是O(n)并且有没有更快的方法在Python中实现这一点? 另外,有没有办法,我可以做到这一点,而无需使用额外的空间。
注意:元素的大小可以是10 ^ 5或更大
n = max(A)
answer = []
seen = set()
for i in A:
if i in seen:
answer.append(i)
else:
seen.add(i)
for i in xrange(1,n):
if i not in A:
answer.append(i)
print ans
答案 0 :(得分:1)
你确实是正确的,这个算法的复杂性是O(n),这是你能达到的最好。完成重复值后,您可以尝试通过中止搜索来优化它。但最坏的情况是你的副本位于列表的后面,你仍然需要完全遍历它。
使用散列(使用一组)是一个很好的解决方案。还有很多其他方法,例如使用Counters
。但这不会改变算法的渐近复杂性。
作为@Emisor建议,您可以利用您拥有1个重复值和1个缺失值的列表的信息。您可能知道如果您的列表没有重复且没有缺失值,那么总结列表中的所有元素将导致1+2+3+..+n
,这可以在数学等价物(n*n+1)/2
当您发现重复值时,您可以计算缺失值,而无需执行:
for i in xrange(1,n):
if i not in A:
answer.append(i)
由于您知道所有值都存在的总和:total = (n*n+1)/2) = 15
,并且您知道哪个值是重复的。通过获取A = [1,4,2,5,1]
数组的总和13
并删除重复的值1
,结果为12
。
获取计算出的总数并从中减去计算出的12
会得到3
。
这一切都可以写成一行:
(((len(A)+1)*(len(A)+2))/2)-sum(A)-duplicate
答案 1 :(得分:0)
轻微优化(我认为)
def lalala2(A):
_max = 0
_sum = 0
seen = set()
duplicate = None
for i in A:
_sum += i
if _max < i:
_max = i
if i in seen:
duplicate = i
elif duplicate is None:
seen.add(i)
missing = -_sum + duplicate + (_max*(_max + 1)/2) # This last term means the sum of every number from 1 to N
return [duplicate , missing]
看起来有点丑陋,我自己做了sum()和max()之类的东西而不是依靠Python的工具。但是通过这种方式,我们只检查每个元素一次。此外,一旦发现副本,它就会停止向集合中添加内容,因为一旦知道最大值,它就可以从中计算缺少的元素