如何快速找到数组中未配对的元素?

时间:2019-06-20 19:37:14

标签: python python-3.x optimization

我正在练习Codility的一些问题。但是,每次我运行问题时,我的性能(运行时)得分都非常低(25%)。您能帮我知道如何改善我的代码,以便获得更高的分数吗?

问题是:

编写函数:

def solution(A)

给定一个数组N,该数组A由满足上述条件的N个整数组成,则返回未配对元素的值。

例如,给定数组A这样:

  A[0] = 9  A[1] = 3  A[2] = 9
  A[3] = 3  A[4] = 9  A[5] = 7
  A[6] = 9

该函数应返回7,如上面的示例所述。

与我相同的代码是:

def solution(A):
# write your code in Python 3.6
    lis=[i for i in A if A.count(i) ==1]
    return lis[0]

输出:

  

medium2   “中等随机测试n = 100,003✘超时错误   被杀达到硬限制:6.000秒”

3 个答案:

答案 0 :(得分:4)

这是因为list.count每次都会搜索整个列表,即O(N)* N或N ** 2。您可以使用collections.Counter来计数某项一次或一次通过的次数,由于它是字典,因此查找为O(1):

from collections import Counter

def solution(A):
    c = Counter(A)
    # this will iterate over all the key/value pairs
    # which is at worst N elements long
    return [k for k, v in c.items() if v==1]

要显示速度增加:

python -m timeit -s "from random import randint; A = [randint(0,500) for i in range(10000)]" "x = [a for a in A if A.count(a)==1]"
10 loops, best of 3: 957 msec per loop


python -m timeit -s "from random import randint; from collections import Counter; A = [randint(0,500) for i in range(10000)]; c = Counter(A)" "x = [s for s, v in c.items() if v==1]"
10000 loops, best of 3: 20.1 usec per loop

即使我每次都创建一个随机列表,但Counter实现在20个试验中的平均最佳运行时间为20.2us,而list.count实现为962.1ms。因此,即使每次运行的时间都不尽相同,但我认为平均值可以显示

答案 1 :(得分:2)

使用itertools.groupby()的版本的性能大约是使用collections.Counter的版本的3倍:

import collections
from itertools import groupby
import timeit

l = [9, 3, 9, 3, 9, 7, 9]

def fn1(lst):
    return [v for v, g in groupby(sorted(lst)) if len([*g]) == 1]

def fn2(lst):
    k = collections.Counter(lst)
    return [i for i in k if k[i] == 1]

print(timeit.timeit(lambda: fn1(l), number=100_000, globals=globals()) )
print(timeit.timeit(lambda: fn2(l), number=100_000, globals=globals()) )

打印:

0.11646193999331445
0.33489679799822625

答案 2 :(得分:0)

尝试以下方法:

import collections 

k = collections.Counter(A)
return [ i for i in k if k[i] == 1]