fibonacci數列是個很常見的面試題,相信你們都見識過,反正我遇見過兩次。遞歸是最容易想到的辦法。可是寫一個遞歸,每每面試官並不滿意,會追問。這個遞歸存在什麼問題啊。有沒有其它辦法啊……。辦法總比問題多,跳跳大路通帝都。下面就總結一下。把程序寫到面試官的心縫裏!python
遞歸法面試
這個遞歸存在的最嚴重的問題就是重複計算,在代碼的遞歸分支裏能夠看到函數被遞歸調用了兩次,那麼不少函數其實都被重複計算了。最後再來解決這個問題。緩存
def fib01(n): if n == 1 or n == 2: return n else: return fib01(n-1) + fib01(n-2)
遞推法1app
使用一個列表來存儲整個fibonnci數列,所求的即爲列表的第n項ide
def fib02(n): if n == 1 or n == 2: return n else: arr = [1, 1, 2] i = 3 for i in range(3, n+1): arr.append(arr[i-1] + arr[i-2]) return arr[n]
遞推法2函數
聲明幾個歷史變量不斷計算數列的值,而且交換變量spa
def fib03(n): if n == 1 or n == 2: return n else: x = 1 y = 2 for i in range(3, n+1): fi = x + y x = y y = fi return y
緩存遞歸中間結果
orm
定義一個字典,將遞歸函數的計算結果存入_fib_cache,每次判斷該函數是否在緩存中,在直接返回,不在,計算並放入緩存遞歸
_fib_cache = {} def fib04(n): if n in _fib_cache: return _fib_cache[n] else: _fib_cache[n] = n if n <= 2 else fib04(n-1) + fib04(n-2) return _fib_cache[n]
有了緩存,生活美好了不少,可是看着有點彆扭。孤零零的_fib_cache,弄個裝飾器多好,這明顯能夠有個裝飾器的。ci
函數裝飾器
def memo(f): cache = {} def decorated(*args): if args in cache: return cache[args] else: cache[args] = f(*args) return cache[args] return decorated
有了這個裝飾器函數,咱們就能夠裝飾咱們的遞歸函數了
@memo def fib01(n): if n == 1 or n == 2: return n else: return fib01(n-1) + fib01(n-2)