我寫(xiě)了一個(gè)函數(shù),計(jì)算斐波那契數(shù)列的第n項(xiàng)數(shù)值
def fib_n(x):
s=[0,1]
if x<=1:
return s[x]
else:
k=2
while (k<=x):
m=s[k-2]+s[k-1]
s.append(m)
k=k+1
return s[x]
但是報(bào)出占用的空間比較大,有另外一種計(jì)算方法是:
def Fibonacci(self, n):
# write code here
if n == 0:
return 0
if n == 1:
return 1
if n == 2:
return 1
if n >= 3:
s = []*n
s.append(1)
s.append(1)
for i in xrange(2,n):
s.append(s[i-1]+s[i-2])
return s[n-1]
我想問(wèn)下,第二種為什么占用空間比較小。
我知道這個(gè)問(wèn)題可能比較簡(jiǎn)單,如果哪位愿意指教,可以告訴我一下,這是哪一部分知識(shí)缺乏?
關(guān)鍵兩點(diǎn):
1.別用尾遞歸,計(jì)算的n的值稍微大一點(diǎn)就會(huì)爆棧。
2.python中數(shù)組的添加元素的過(guò)程
參看鏈接:http://hyry.dip.jp/tech/slice...
額外分配的內(nèi)存與數(shù)組的大小成正比
建議了解下底層數(shù)組的實(shí)現(xiàn)(為什么占用空間會(huì)比較大),以及計(jì)算機(jī)程序大致是怎么運(yùn)行的(為什么尾遞歸會(huì)出現(xiàn)爆棧問(wèn)題)。
我覺(jué)得其他人都只是提供更好的計(jì)算斐波那契的方法,卻不是回答 第二種為什么占用空間比較?。?/strong>的啊。
感謝 起風(fēng)了 對(duì) s = []*n 指出的錯(cuò)誤。s = []*n 其實(shí)與 s = [] 等價(jià)。
以下是我測(cè)試的代碼:
import sys
def fib_n(x):
s = [0, 1]
if x <= 1:
return s[x]
else:
k = 2
while (k <= x):
m = s[k - 2] + s[k - 1]
s.append(m)
k = k + 1
print("fib_n: %s len=%s" % (sys.getsizeof(s), len(s)))
return s[x]
def Fibonacci(n):
# write code here
if n == 0:
return 0
if n == 1:
return 1
if n == 2:
return 1
if n >= 3:
s = []*n
s.append(1)
s.append(1)
for i in range(2,n):
s.append(s[i-1]+s[i-2])
print("Fibonacci: %s len=%s" % (sys.getsizeof(s), len(s)))
return s[n-1]
fib_n(90) # fib_n: 792 len=91
Fibonacci(90)# Fibonacci: 792 len=90
第二種占用空間更大。但是第二種的數(shù)組元素個(gè)數(shù)明明是更小的啊,這是為什么?
這是因?yàn)楹竺鎯删?s.append(1) 會(huì)占用一些空間:
print(sys.getsizeof([1,1])) # 80
s = []
s.append(1)
s.append(1)
print(sys.getsizeof(s)) # 96
python中數(shù)組的實(shí)現(xiàn)是類似 C++ 中 vector 的??臻g和隨元素占用而增長(zhǎng),因此會(huì)有一些空間是還沒(méi)被利用的,比如一個(gè)僅為 3 個(gè)元素的宿主,它的內(nèi)存上表現(xiàn)是:
[1, 2, 3, NULL, NULL, NULL, NULL]
按照增長(zhǎng)規(guī)則:
new_allocated = (size_t)newsize + (newsize >> 3) + (newsize < 9 ? 3 : 6);
比如 [1,2] 下一個(gè) append 就需要3個(gè)空間,就將 newsize = 3 代入規(guī)則,得出數(shù)組新申請(qǐng)的空間。
第一種增長(zhǎng)的空間分別為: 2, 6, 10, 18, 27, 37, 48, 61, 75, 91
第二種增長(zhǎng)的空間分別為: 0, 4, 8, 16, 25, 35, 46, 58, 72, 88, 106
因此,不一定是哪種方法占的空間更低。例如,當(dāng) n = 80 時(shí),第二種方法占用空間就更低。
首先你寫(xiě)的函數(shù)時(shí)間空間效率不是很高。
至于空間的問(wèn)題我暫時(shí)看出來(lái)的是第一種總會(huì)創(chuàng)建s變量,第二種在n<3的情況下不會(huì)。
我的建議是這種寫(xiě)法(Python3)。
from functools import lru_cache
@lru_cache(maxsize = 10000)
def fib(n):
if n < 2:
return 1
else:
return fib(n - 1) + fib(n - 2)
其中l(wèi)ru_cache是Python自帶的利用LRU算法的緩存模塊,意思就是算過(guò)的fib(n)(最近計(jì)算過(guò)的10000個(gè)之內(nèi))會(huì)緩存下來(lái),直接使用,整體上和使用循環(huán)效率一致。
北大青鳥(niǎo)APTECH成立于1999年。依托北京大學(xué)優(yōu)質(zhì)雄厚的教育資源和背景,秉承“教育改變生活”的發(fā)展理念,致力于培養(yǎng)中國(guó)IT技能型緊缺人才,是大數(shù)據(jù)專業(yè)的國(guó)家
達(dá)內(nèi)教育集團(tuán)成立于2002年,是一家由留學(xué)海歸創(chuàng)辦的高端職業(yè)教育培訓(xùn)機(jī)構(gòu),是中國(guó)一站式人才培養(yǎng)平臺(tái)、一站式人才輸送平臺(tái)。2014年4月3日在美國(guó)成功上市,融資1
北大課工場(chǎng)是北京大學(xué)校辦產(chǎn)業(yè)為響應(yīng)國(guó)家深化產(chǎn)教融合/校企合作的政策,積極推進(jìn)“中國(guó)制造2025”,實(shí)現(xiàn)中華民族偉大復(fù)興的升級(jí)產(chǎn)業(yè)鏈。利用北京大學(xué)優(yōu)質(zhì)教育資源及背
博為峰,中國(guó)職業(yè)人才培訓(xùn)領(lǐng)域的先行者
曾工作于聯(lián)想擔(dān)任系統(tǒng)開(kāi)發(fā)工程師,曾在博彥科技股份有限公司擔(dān)任項(xiàng)目經(jīng)理從事移動(dòng)互聯(lián)網(wǎng)管理及研發(fā)工作,曾創(chuàng)辦藍(lán)懿科技有限責(zé)任公司從事總經(jīng)理職務(wù)負(fù)責(zé)iOS教學(xué)及管理工作。
浪潮集團(tuán)項(xiàng)目經(jīng)理。精通Java與.NET 技術(shù), 熟練的跨平臺(tái)面向?qū)ο箝_(kāi)發(fā)經(jīng)驗(yàn),技術(shù)功底深厚。 授課風(fēng)格 授課風(fēng)格清新自然、條理清晰、主次分明、重點(diǎn)難點(diǎn)突出、引人入勝。
精通HTML5和CSS3;Javascript及主流js庫(kù),具有快速界面開(kāi)發(fā)的能力,對(duì)瀏覽器兼容性、前端性能優(yōu)化等有深入理解。精通網(wǎng)頁(yè)制作和網(wǎng)頁(yè)游戲開(kāi)發(fā)。
具有10 年的Java 企業(yè)應(yīng)用開(kāi)發(fā)經(jīng)驗(yàn)。曾經(jīng)歷任德國(guó)Software AG 技術(shù)顧問(wèn),美國(guó)Dachieve 系統(tǒng)架構(gòu)師,美國(guó)AngelEngineers Inc. 系統(tǒng)架構(gòu)師。