至於其他的答案中指出,你並不需要擔心,除非你的oil_changes
名單非常長。然而,隨着「基於數據流的」計算的粉絲,我認爲這是有趣地指出,itertools
提供所有你需要計算在O(1)空間(當然O(N)時間你next_oil
價值的工具! - )不管N有多大,就是len(next_oil)
,得到。
izip
本身是不夠的,因爲它不僅降低了一點乘法不變,但離開你的空間需求爲O(N)。關鍵的思想,使這些需求降到O(1)配對izip
與tee
- 和避免列表理解,這將是在太空O(N)反正,有利於良好的簡單的老式循環! - )。這裏說到:
it = iter(oil_changes)
a, b = itertools.tee(it)
b.next()
thesum = 0
for thelen, (i, j) in enumerate(itertools.izip(a, b)):
thesum += j - i
last_one = j
next_oil = last_one + thesum/(thelen + 1)
而不是從列表中取切片,我們取一個迭代器就可以了,它三通(製造其兩個獨立的可推進克隆),並提前,有一次,一個克隆,b
。 tee
需要空間O(x)其中x是各種克隆進程之間的最大絕對差值;在這裏,兩個克隆的進步最多隻相差1,所以空間需求顯然是O(1)。
izip
對兩個略微歪斜的克隆迭代器進行一次一個「壓縮」,我們將它打扮成enumerate
,以便我們可以跟蹤我們經過該循環的次數,即長度我們正在迭代迭代(我們需要最終表達式中的+1,因爲enumerate
從0開始!)。我們用一個簡單的+=
來計算總和,這對數字來說很好(sum
甚至更好,但它不會跟蹤長度!)。
這是誘人的後循環使用last_one = a.next()
,但是這是行不通的,因爲a
實際上是用盡 - izip
推進其參數iterables左到右,所以它擁有先進的a
最後一次實現b
結束前! - )。這是確定的,因爲Python循環變量不在範圍循環本身的限制 - 在循環後,j
仍然有最後被推進b
提取izip
放棄了(就像thelen
仍然通過返回的最後一個計數值之前的值enumerate
)。我仍然在命名last_one
,而不是直接在最終表達式中使用j
,因爲我認爲它更清晰,更具可讀性。
所以有它 - 我希望這是有益的 - - !) - 儘管你提出了這個當時的具體問題的解決方案,幾乎可以肯定的是矯枉過正。我們意大利人有一句古老的諺語 - 「Impara l'Arte,e mettila da parte!」... ...「學習藝術,然後放在一邊」 - 我認爲這很適用於此:學習是件好事先進的和複雜的方式來解決非常棘手的問題,以防萬一遇到它們,但是爲了簡單和直接,您需要去解決簡單,普通問題的大量常見問題 - 不適用最有可能贏得的高級解決方案「T需要 - !)
有趣的是,這裏的答案(除了當然的約翰·馬金的答案)中最快的運行時間的diff結果您的備選定義。 – 2009-07-10 01:56:44
如果len(條目)> 0,那麼平均值可能只是sum(items)/ len(items)? – Martlark 2011-07-31 02:52:41