1. 程式人生 > >Python:遞迴輸出斐波那契數列

Python:遞迴輸出斐波那契數列

今天學習Python的時候做一道練習題,題目是這樣的:

題目 匯入

  • 問題
    有一對兔子,從出生後第3個月起每個月都生一對兔子,小兔子長到第三個月後每個月又生一對兔子,假如兔子都不死,問每個月的兔子總對數為多少?

  • 分析
    簡單的分析了一下,發現這個問題其實就是斐波那契數列問題。
    第一個月兔子對數為1,
    第二個月兔子對數還是1,
    第三個月,開始生小兔子啦,那麼總的對數是1+1=2,
    第四個月,老兔子又生了,那麼1(最開始的老兔子)+1(第四個月老兔子生的)+1(第三個月老兔子生的)=3
    第五個月,1(1老)+1(第五個月老兔子生)+1(第四個月老兔子生)+1(第三個月老兔子生)+1(第三個月老兔子生的小兔子也生了)=5
    第六個月,1(1老)+1(第六個月老兔子生)+1(第五個月老兔子生)+1(第四個月老兔子生)+1(第三個月老兔子生)+1(第三個月老兔子生的小兔子也生了)+1(第三個月老兔子生的小兔子又生了)+1(第四個月老兔子生的小兔子也生了)=8




    可以發現,每個月的兔子的對數為 1,1,2,3,5,8,13,
    因此,經過一個簡單的分析,可以看出來,這道題就是考察的斐波那契數列的。

Python程式碼實現

這個程式碼實現的話,應該是有多種實現方法的。

  • 直接輸出
def rabbit1(n):
    f1=1
    f2=1
    if (n==1 or n==2):
        return 1
    else:
        for i in range(3,n+1):
            f1,f2=f2,f1+f2
        return f2
  • 遞迴輸出方式一
    這個斐波那契數還可以使用遞迴進行輸出,就是非常直觀的遞迴計算。
def rabbit2(n):
    if (n==1 or n==2):
        return 1
    else:
        return rabbit2(n-1)+rabbit2(n-2)
  • 遞迴輸出方式二
    這種方式是把之前算過的斐波那契數存在字典中,這樣的話遞迴要用的話就直接存取,而不是去重新計算。
def rabbit3(n,rabbits={1:1,2:1}):
    if n in rabbits:
        return rabbits[n]
    res=rabbit3(n-1)+rabbit3(n-2)
    rabbits[n]=res
    return
res

三種方式的討論

對於三種方式而言,都可以直接輸出結果來。

print(rabbit1(10))
print(rabbit2(10))
print(rabbit3(10))

輸出結果為:

55
55
55

可以看出來,程式是沒有錯的。
現在n=36,再試一試,
第一種方式結果

14930352
    [Finished in 0.3s]

第二種方式結果為:

14930352
    [Finished in 4.7s]

第三種方式結果為:

14930352
    [Finished in 0.3s]

可以看出來,直接遞迴貌似結果就差遠了。而第二種遞迴,把之前的資料存起來而不是計算則就要快很多了。
至於第一種方式,是相當快得,當n很大,依舊可以秒算。比如說n=10000,第一種方式可以計算。而第三種方式就不行了,告訴我不能計算了,報錯。至於為什麼還沒有弄明白。

關於使用Python輸出斐波那契數列的補充

今天在學習python迭代器和生成器,大致記錄一下:
迭代器
迭代是Python最強大的功能之一,是訪問集合元素的一種方式。。
迭代器是一個可以記住遍歷的位置的物件。
迭代器物件從集合的第一個元素開始訪問,直到所有的元素被訪問完結束。迭代器只能往前不會後退。
迭代器有兩個基本的方法:iter() 和 next()
字串,列表或元組物件都可用於建立迭代器:

#import sys         # 引入 sys 模組

list=[1,2,3,4]
it = iter(list)    # 建立迭代器物件
flag=True
while True:
    try:
        print (next(it))
    except StopIteration:
        #sys.exit()
        flag=False

利用迭代器代替for迴圈,進行列表資料的遍歷輸出。

生成器
在 Python 中,使用了 yield 的函式被稱為生成器(generator)。
跟普通函式不同的是,生成器是一個返回迭代器的函式,只能用於迭代操作,更簡單點理解生成器就是一個迭代器。
在呼叫生成器執行的過程中,每次遇到 yield 時函式會暫停並儲存當前所有的執行資訊,返回yield的值。並在下一次執行 next()方法時從當前位置繼續執行。
以下例項使用 yield 實現斐波那契數列:

def iteration_yield(it):
    flag = True
    # a=0
    while flag:
        try:
            print(next(it), end=" ")
        except StopIteration:
            # sys.exit()
            flag = False
    # print(a)


def fibonacci(n):
    a, b, counter = 0, 1, 0
    while True:
        if counter > n:
            return
        yield a
        a, b = b, a + b
        print('%d,%d' % (a, b))
        counter += 1
f = fibonacci(1000)
iteration_yield(f)

這裡寫圖片描述

更多具體的內容可以從這個地方學習到: