查找数组的第一个副本

时间:2017-10-01 14:27:37

标签: python algorithm list duplicates

我决定学习python并使用CodeFight进行训练。第一次采访练习是关于找到数组的第一个副本并返回它或者如果没有则返回-1。这是我写的代码:

def firstDuplicate(a):
b=[]
print(len(a))
for i in range(len(a)):
    if a[i] in b:
        return(a[i])
    elif a[i] not in b and i == (len(a)-1):
        return(-1)
    else:
        b.append(a[i])

我通过除了最后3个以外的所有测试。我说我的程序执行时间超过4000毫秒。我猜数组很长,副本就在最后。如何减少执行时间?提前谢谢。

4 个答案:

答案 0 :(得分:5)

您当前的解决方案使用list进行簿记,in成员资格测试始终是线性的。您应该考虑使用set,或者在Counter中保留值的计数。

两种情况下的想法都不是在没有必要的情况下遍历完整列表。通过一点额外空间,您可以提高性能。

def firstDuplicateSet(a):
    seen = set()
    for i in a:
        if i in seen:
            return i
        seen.add(i)

    return -1
from collections import Counter

def firstDuplicateCounter(a):
    c = Counter()
    for i in a:
        c[i] += 1
        if c[i] > 1:
            return i

    return -1

答案 1 :(得分:3)

你可以这样重写:

def opt_first_duplicate(arr):
    unique_nb = set()
    for nb in arr:
        if nb in unique_nb:
            return nb
        else: 
            unique_nb.add(nb)
    return -1

我在一个jupyter笔记本中使用%% timeit magic命令比较我们的解决方案,并使用这样生成的测试数组:

import random
test_array = [random.randint(0, 10000000) for i in range(5000)]

其中一个运行示例:

firstDuplicate:每循环401 ms±1.61 ms(7次运行的平均值±标准差,每次1次循环)

opt_first_duplicate:每循环600μs±20.2μs(平均值±标准偏差,7次运行,每次1000次循环)

优化代码的2个技巧:

  • 使用集合代替列表来查找已经看过的整数
  • 第二次测试(elif)没用,因为你已经测试了整数
  • 的存在

希望它能解决你的问题

On set比列表更快:What makes sets faster than lists in python?

答案 2 :(得分:0)

from collections import Counter
list1 = [1,2,2,3,4,4]
dict1 = Counter(list1)
duplist = [key for (key,value) in dict1.items()if value >1]
for item in list1:
    if item in duplist:
        print ('first dup',item )
        break

答案 3 :(得分:0)

这不是问题的确切答案,但这可能会帮助许多开发者登陆这里。这里使用了列表理解和枚举。

mylist=[1,2,3,4,5,1,6,7,8,9,5]
length=len(mylist)

all_duplicates=[v for i,v in enumerate(mylist) if i < length-1 and v in mylist[i+1:]]
[1, 5]

first_duplicate=next((v for i,v in enumerate(mylist) if i < length-1 and v in mylist[i+1:]),None)
1

我希望代码能自我解释