筆者是一枚準備找工作的新手,為了準備一些演算法思想,開啟了改善腦迴路計畫。記錄我思考問題的過程,如果能啟發一下其他道友就更好了。標題原創,各位大大別亂用哈~
斐波那契(fibonacci)數列是乙個非常簡單的遞迴數列,除第乙個和第二個數外,任意乙個數都可由前兩個數相加得到。形如:1, 1, 2, 3, 5, 8, 13…
要求就是:乙個函式fibonacci(n),接受引數n為數列的長度,返回物件是長度為n的斐波那契數列
宣告:程式用的是python
第一步,寫關鍵部分的**。返回斐波那契數列中的數,基本規律是這乙個數等於前兩個數相加:result = late1 + late2
。其中,三個數的順序是...late1, late2, result...
。由此可見,返回斐波那契數列中的乙個數需要前面兩個數已知。所以,不僅要為返回值設定變數result,還要為計算值設定兩個變數late1和late2。
def
fib(n, late1, late2):
if n < 0:
'''報錯'''
elif n == 0
or n == 1:
return
1elif n >= 2:
result = late1 + late2
return result
問題來了:哪兒來的late1和late2以供計算呢,畢竟整體而言,只有乙個輸入引數,那就是n。**第二步,解決第一步剩餘的相關問題。**late1和late2也是數列中的數,是之前計算的result,那麼,在每次計算result的時候,我們都應該保留兩個值(當前計算出的返回值及其前乙個數)以供計算下乙個result。
def
fib(n, late1, late2):
if n < 0:
'''報錯'''
elif n == 0:
return
0, 1
elif n == 1:
return
1, 1
elif n >= 2:
result = late1 + late2
return late2, result
deffibonacci
(n):
late, cur = 1, 1
# 初始當前值為1,前乙個值為1
rslist = # 數列的儲存列表
for i in range(n):
late, cur = fib(i, late, cur)
print rslist
'''產生乙個長度為10的fibonacci數列'''
for x in fibonacci(10):
print x,
# 輸出為[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
第三步,對**中的特殊情況特殊處理。要求輸入的n必須為大於0的整數。在這裡,先預設輸入的都是整數,只對n<0的情況進行處理。n<0時,不返回值並且丟擲引數異常。
def
fib(n, late1, late2):
if n == 0:
return
0, 1
elif n == 1:
return
1, 1
elif n >= 2:
result = late1 + late2
return late2, result
deffibonacci
(n):
if n <= 0:
'''報錯'''
print
'error'
raise valueerror, 'n must be an integer greater than zero!!'
late, cur = 1, 1
# 初始當前值為1,前乙個值為1
rslist = # 數列的儲存列表
for i in range(n):
late, cur = fib(i, late, cur)
return rslist
一般**都有三個要求,基本要求是功能,高階要求是效率,終極要求是可復用。到此我們已經完成了基本功能要求了,筆者當下心滿意足,先去玩耍了~
最近看到別人寫的乙個更簡單的方式, 如下:
def
fib(n):
n, late, result = 0, 0, 1
rslist =
while n < max:
late, result = result, late + result
n = n + 1
return rslist
deffibonacci
(n):
if n <= 0:
'''報錯'''
print
'error'
raise valueerror, 'n must be an integer greater than zero!!'
else:
return fib(n)
具體改進的關鍵點有三個:
我們的**中需要儲存當前返回值和它之前的值。斐波那契數列第乙個數是1, 它前面並沒有其他數了,但是,因為我們只是用儲存的兩個數進行相加來計算返回值,所以,
可以將第零個數設為0。
當輸入為2時,函式需要返回[1, 1]。計算時, 第二個數通過上面的方法,計算為result = late1 + late2 = 0 + 1
。但是第乙個數的計算怎麼辦?
可以採用先儲存結果在計算的方式(跟籬笆樁的情況不太一樣),雖然最後會多算乙個多餘值,不過無傷大雅。
現在fib()函式的引數只要乙個。兩個函式的結構稍作了改變。
如果因為輸入n特別大,可能導致輸出的列表特別大,造成記憶體溢位。為了控制儲存空間,我們應該將輸出的列表用generator生成器來表示。
舉個生成器和普通可迭代物件(list)的列子:
iter_list = range(10) # 普通可迭代物件
gene_list = xrange(10) # 生成器
print
type(iter_list)
print
type(gene_list)
for i in iter_list:
print i,
for i in gene_list:
print i,
print
print iter_list
print gene_list
---輸出↓↓↓---
'list'>
'xrange'>01
2345
6789
0123
4567
89[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
xrange(10)
可以看出:
生成器和普通迭代器的效果是一樣的
但是他們的直接列印結果不一樣,是因為普通迭代器是先產生了整個陣列並儲存在記憶體中;而生成器只是乙個生成資料的方式,當有需要的時候才會產生下乙個值,因此也更省記憶體空間。
用乙個生成器來實現斐波那契額數列:
class
fab(object):
def__init__
(self, max):
self.max = max
self.n, self.a, self.b = 0, 0, 1
def__iter__
(self):
return self
defnext
(self):
if self.n < self.max:
r = self.b
self.a, self.b = self.b, self.a + self.b
self.n = self.n + 1
return r
raise stopiteration()
或者是利用python的yield命令:
# 簡介版,使用yield
deffab
(max):
n, a, b = 0, 0, 1
while n < max:
yield b
a, b = b, a + b
n = n + 1
結果都是一樣的:
for n in fab(10):
print n,
---輸出↓↓↓---11
2358
1321
3455
在 for 迴圈執行時,每次迴圈都會執行 fab 函式內部的**,執行到 yield b 時,fab 函式就返回乙個迭代值,下次迭代時,**從 yield b 的下一條語句繼續執行,而函式的本地變數看起來和上次中斷執行前是完全一樣的,於是函式繼續執行,直到再次遇到 yield。 斐波那契數列 斐波那契數列python實現
斐波那契數列 fibonacci sequence 又稱 分割數列 因數學家列昂納多 斐波那契 leonardoda fibonacci 以兔子繁殖為例子而引入,故又稱為 兔子數列 指的是這樣乙個數列 1 1 2 3 5 8 13 21 34 在數學上,斐波納契數列以如下被以遞推的方法定義 f 1 ...
迴圈斐波那契數列 斐波那契數列應用
什麼是斐波那契數列 斐波那契數列指的是這樣乙個數列 1,1,2,3,5,8,13,21,34,55,89,144 這個數列從第3項開始,每一項都等於前兩項之和 台階問題 有一段樓梯有10級台階,規定每一步只能跨一級或兩級,要登上第10級台階有幾種不同的走法?這就是乙個斐波那契數列 登上第一級台階有一...
斐波那契數列
1 題目描述 大家都知道斐波那契數列,現在要求輸入乙個整數n,請你輸出斐波那契數列的第n項。斐波那契數列的定義如下 輸入 輸入可能包含多個測試樣例,對於每個測試案例,輸入包括乙個整數n 1 n 70 輸出 對應每個測試案例,輸出第n項斐波那契數列的值。2 這是九度上的乙個題,要求時間限制1秒,整數的...