關於遞歸的思考

以前有接觸過遞歸,看到別人寫的遞歸函數的代碼,好生羨慕,怎麼就能寫這麼好呢?我怎麼就想不到這樣寫呢?如此等等。python

就拿fibonacci函數來講吧,一個普通的函數可能這樣寫:算法

def fib(n):
    if n == 0:
        return 0
    elif n == 1:
        return 1
    else:
        return fib(n-1) + fib(n-2)

我看到這個函數的思考方式是這樣的:app

1. 當n=0時:返回0
2. 當n=1時:返回1
3. 當n=2時:
    1. 首先去調用n=1,返回1
    2. 再去調用n=0,返回0
    3. 把0和1相加返回1
4. 當n=3時:
    1. 調用n=2
        1. 調用n=1,返回1
        2. 調用n=0,返回0
        3. 相加返回1
    2. 調用n=1,返回1
    3. 把1和1相加返回2
5. 等等

想到這我頭都要爆了,完全被人家的函數折服了,看來我是寫不成這麼好的函數了。函數

但我轉念一想,這個函數的本質是fibnacci序列,我何不迴歸fibonacci自己呢?fibonacci用數學公式表示應該是這樣:spa

2016-07-07-thinking-in-recursion-formula-of-fibonacci.png

看到公式我恍然大悟,上面那個函數不就是根據這個公式直接翻譯的嘛!原來我一直思考都是順着函數的代碼思考,這樣確定會以爲很難,
正確的思考方式應該是從算法出發而後再寫代碼。翻譯

通過了上面的慘痛教訓看看我能不能寫出正確的fibonacci序列函數,分段函數的公式應該是這樣的:code

2016-07-07-thinking-in-recursion-formula-of-fibonacci-sequence.png

那麼直接寫成代碼就應該是這樣的:orm

def fib_seq(n):
    seq = []
    if n == 0:
        seq.append(0)
    else:
        seq.extend(fib_seq(n-1))
        seq.append(fib(n))
    return seq

咦,這兩個append好像能夠合併:遞歸

def fib_seq(n):
    seq = []
    if n > 0:
        seq.extend(fib_seq(n-1))
    seq.append(fib(n))
    return seq

哇,原來如此!ip

相關文章
相關標籤/搜索