在考试中,我被问到以下哪项功能最有可能跑得更快:
def f1():
a = []
for j in range(100000): a.append(j*j)
for j in range(100000):
if 99999*j == a[j]:
print("yes")
def f3():
d = {}
for j in range(100000): d[j] = j*j
for j in range(100000):
if 99999*j in d:
print("yes")
很明显,in
和==
都是O(1)。
但是,我很惊讶地看到f1
跑得更快。
任何解释都将不胜感激。
答案 0 :(得分:1)
常数成本不同。仅仅因为两个算法是O(1)并不能使它们等效。例如,字典平均只有O(1) ,而列表查找总是O(1)。
你需要分析差异,但你在这里做出错误的假设。 f1
按列表中的索引查找元素,然后测试是否相等。 f2
测试字典中的元素。但是,字典成员资格测试涉及散列和相等性测试(如果该位置有对象)。
因此,真正的区别在于哈希与列表查找。列表查找获胜,因为其成本仍为O(1),但散列可以是O(N),基于被散列对象的大小。差异解释了你看到的时间:
>>> import timeit
>>> a = [j * j for j in range(100000)]
>>> timeit.timeit('a[5000]', 'from __main__ import a', number=10**7)
0.26793562099919654
>>> timeit.timeit('_h(5000)', '_h = hash', number=10**7)
0.4080043680005474
散列的实际成本通常在所有字典成员资格查找中取平均值;连同字典的O(N)查找的可能的最坏情况,使字典查找仅平均值 O(1)。另一方面,列表查找总是O(1)。
答案 1 :(得分:0)
很明显,in和==都是O(1)。
- 不,不是。
对于词典和集合的in的复杂性是平均O(1)和最差(具有大量冲突)直到O(N)。 为了更好地理解哈希表,词组,集合等如何工作,请阅读此内容 - How are Python's Built In Dictionaries Implemented