簡體   English   中英

為什么添加到列表的前面需要二次時間?

[英]Why does adding to the front of the list take quadratic time?

此代碼示例取大O(N ^ 2)

results = []

for i in range(1000000)
    result = [f(i)] + results

此代碼示例取大O(N)

results = []

for i in range(1000000)
    result = results + [f(i)]

為什么在這兩種算法的Big O中存在如此明顯的差異,唯一的區別是一個被添加到列表的前面而另一個被添加到列表的后面?

這對Java也適用嗎?

因為列表已針對追加進行了優化,而不是預先添加:如果您預先添加,則需要重新創建整個列表。

如果您希望數據結構能夠以相同的效率在兩端追加,請使用collections.deque

這種情況的原因是因為CPython在C中實現並使用C數組作為列表的后備存儲,並且必須在將元素添加到列表前面之前重新分配和移動元素。

回答問題的后半部分,“這對Java也適用嗎?” 答案是肯定的,Java中的原始數組和Java中的ArrayList都不允許在不重新分配和移動元素的情況下預先添加到列表中。

此外,您的代碼存在缺陷,因為您要分配result而不是results ,因此您實際上並未導致問題中所述的二次性能。 演示此行為的更好方法如下:

results = []
for i in range(1000000):
    results.insert(0, f(i))

和追加版本:

results = []
for i in range(1000000):
    results.append(f(i))

或者使用timeit模塊:

$ python -m timeit 'results = []' 'for i in range(10000): results.insert(0, i)'
10 loops, best of 3: 50.9 msec per loop
$ python -m timeit 'results = []' 'for i in range(10000): results.append(i)'
1000 loops, best of 3: 794 usec per loop

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM