为什么这个O(n ^ 2)解决方案比O(n)解决方案更快?

时间:2017-01-12 03:13:46

标签: python algorithm performance set timeit

编辑:抱歉!我似乎不经意地复制粘贴了相同的代码。

问题:

  

给出从0到N-1的数字列表,您的工作就是找到遗失的数字   数。你的程序应该采用整数列表并返回一个   单个整数(缺少的数字)。

即。输入[0, 1, 3, 4, 5]应返回2

我找到了两个解决方案,一个在O(n)中,一个在(On ^ 2)中。

O(n)解决方案

def alt_find_missing(input_list):
    input_sum = sum(input_list)
    range_sum = sum([i for i in range(min(input_list), max(input_list)+1)])
    return range_sum - input_sum

O(n ^ 2)解决方案

def find_missing(input_list):
    input_set = set(input_list)
    for i in range(min(input_list), max(input_list)+1):
        if i not in input_set:
            return i

但是,在多个timeit测试中,O(n ^ 2)解决方案的运行速度比O(n)快:

List with 4 elements, using for ... in set (x 1 000 000)
1.1550223514080038
List with 4 elements, using difference of sums (x 1 000 000)
1.391524411772641
List with 100 elements, using for ... in set (x 1 000 000)
8.43574248785071
List with 100 elements, using difference of sums (x 1 000 000)
8.94695660741872
List with 1000 elements, using for ... in set (x 100 000)
8.1138781071155
List with 1000 elements, using difference of sums (x 100 000)
8.383110816298519

为什么会这样?

1 个答案:

答案 0 :(得分:2)

第二种算法不是O(n ^ 2)。集查找是O(1)并且迭代集合是O(n)。因此,两种算法之间的差异是由于不同的常数因素造成的。

这是一个简短的脚本,显示了两个函数的线性行为

import timeit
from functools import partial
from matplotlib import pyplot as plt

def alt_find_missing(input_list):
    input_sum = sum(input_list)
    range_sum = sum([i for i in range(min(input_list), max(input_list)+1)])
    return range_sum - input_sum


def find_missing(input_list):
    input_set = set(input_list)
    for i in range(min(input_list), max(input_list)+1):
        if i not in input_set:
            return i


t1=[]
t2=[]

rng=range(10000,1000000,10000)

for n in rng:
    func1=partial(find_missing,range(n))
    func2=partial(alt_find_missing,range(n))
    t1.append(timeit.timeit(func1,number=5))
    t2.append(timeit.timeit(func2,number=5)) 

plt.plot(rng,t1, label='Find missing')
plt.plot(rng,t2, label='Alt find missing')
plt.ylabel('Execution time')
plt.xlabel('Problem size')
plt.legend()
plt.show()

结果对我来说看起来非常线性:)当然在某些问题大小上会出现一些特殊情况,但没有什么可以将结果显着地抛出线性区域。

的问候。 Two linear functions