Python 查找数组的第一个副本
我决定学习python,并使用CodeFight进行训练。第一次面试练习是找到数组的第一个副本并返回它,如果没有,则重新运行-1。这是我写的代码:Python 查找数组的第一个副本,python,algorithm,list,duplicates,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
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])
我通过了所有的考试,除了最后三次。我说我的程序执行时间超过4000毫秒。我猜数组很长,副本在末尾。如何减少此执行时间?提前感谢。您当前的解决方案使用
列表
进行簿记,中的成员资格测试在时间上始终是线性的。你应该考虑使用<代码> SET/COM>,或者在<代码>计数器< /代码>中保持值的计数。
在这两种情况下,如果没有必要,就不要迭代整个列表。使用一点额外的空间,可以提高性能
您可以这样重写它:
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
import random
test_array = [random.randint(0, 10000000) for i in range(5000)]
我将我们在jupyter笔记本中使用%%timeit magic命令的解决方案与通过以下方式生成的测试阵列进行了比较:
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
import random
test_array = [random.randint(0, 10000000) for i in range(5000)]
其中一个运行的示例:
第一次重复:每个回路401 ms±1.61 ms(7次运行的平均值±标准偏差,每个回路1次)
选择第一个重复:每个回路600µs±20.2µs(7次运行的平均值±标准偏差,每个1000个回路)
优化代码的两个技巧:
- 使用集合而不是列表查找已看到的整数
- 第二个测试(elif)是无用的,因为您已经测试了整数的存在性
希望它能解决你的问题
在比列表快的集合上:检查a[i]not in b
是不必要的,因为您已经在的else分支中了。如果a[i]in b
也在b
中,最明显的优化是将b
更改为set
。对循环使用列表理解而不是会更快。这将改变整个代码。可以做很多事情来加快速度。一种是使用更有效的检查,查看您是否在之前遇到一个值(即,一个集合)。另一个是避免无意义的重复工作(这只是常识)。每次迭代检查一次重复,一旦排除了重复,就不要再检查第二次,使运行时间加倍。并停止进行冗余的列表结束检查。让循环正常退出,并在循环外返回-1。这也修复了空列表的错误,您将返回None而不是-1。好的,非常感谢,我将在python.org上的wiki上查看集合,因为我还没有见过它们。很抱歉,我没有将其发布在代码审查上,我将确保以后这样做。
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