我做了功課,並且意外地發現了算法速度的奇怪不一致。 這裏是兩個版本的代碼相同的功能bur有1個不同:在第一版本中我使用3次數組發生器來過濾一些數組,並在第二版本中我使用1 for循環與3 if語句做相同的過濾工作。比較列表推導和顯式循環(3個數組生成器的循環速度快於1)
所以,這裏的第一個版本代碼:
def kth_order_statistic(array, k):
pivot = (array[0] + array[len(array) - 1]) // 2
l = [x for x in array if x < pivot]
m = [x for x in array if x == pivot]
r = [x for x in array if x > pivot]
if k <= len(l):
return kth_order_statistic(l, k)
elif k > len(l) + len(m):
return kth_order_statistic(r, k - len(l) - len(m))
else:
return m[0]
這裏的第二個版本代碼:
def kth_order_statistic2(array, k):
pivot = (array[0] + array[len(array) - 1]) // 2
l = []
m = []
r = []
for x in array:
if x < pivot:
l.append(x)
elif x > pivot:
r.append(x)
else:
m.append(x)
if k <= len(l):
return kth_order_statistic2(l, k)
elif k > len(l) + len(m):
return kth_order_statistic2(r, k - len(l) - len(m))
else:
return m[0]
IPython的輸出爲第1版:
In [4]: %%timeit
...: A = range(100000)
...: shuffle(A)
...: k = randint(1, len(A)-1)
...: order_statisctic(A, k)
...:
10 loops, best of 3: 120 ms per loop
而對於第二版本:
In [5]: %%timeit
...: A = range(100000)
...: shuffle(A)
...: k = randint(1, len(A)-1)
...: kth_order_statistic2(A, k)
...:
10 loops, best of 3: 169 ms per loop
那麼爲什麼第一個版本比第二個版本快呢?我還使用filter()函數取代了數組生成器的第三個版本,它比第二個版本(每個循環得到218 ms)要慢。
列表解析通常比等效的循環更快。擴展列表(您的附加功能)也可能比填寫已知大小的列表更加昂貴。 –
顯着增加你的名單大小......我認爲你會發現差距或多或少是恆定的......你正在交易空間的時間,但他們*大致*相等(發電機上有一點點的開銷/迭代器vs列表) –
@SohierDane這是我的想法。列表理解清楚創建列表的操作將會是什麼,因此可以對其執行優化。根據元素構建列表元素,Python無法對未來的計算或內存使用情況做出任何假設。 – sdsmith