Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 查找数组的第一个副本_Python_Algorithm_List_Duplicates - Fatal编程技术网

Python 查找数组的第一个副本

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

我决定学习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])

我通过了所有的考试,除了最后三次。我说我的程序执行时间超过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