青蛙跳臺階-遞歸思想解算

問題:一只青蛙一次可以跳上一級臺階,也可以跳上兩級臺階。求該青蛙跳上n級臺階總共有多少種跳法?

思路:要跳上 第n級 臺階,要么從第 n-1 級臺階跳上,要么從第 n-2 級臺階跳上,只有這兩種方法。因此,跳上 第n級 臺階的跳法等于跳上 第n-1級 的跳法 加上 跳上第n-2級的跳法。采用遞歸算法實現。

基線條件:if n == 0 or n == 1 or n == 2: return n

遞歸公式:f(n) = f(n-1) + f(n-2)

代碼:

def stairs(n):

    # 基線條件 => 跳出遞歸調用
    if n == 0 or n == 1 or n == 2:
        return n
    
    # 遞歸公式:實現遞歸調用
    return stairs(n-1) + stairs(n - 2)


print(stairs(5))

>>>
8

2020年11月30日修改:
使用遞歸求解,當臺階數n過大時(>50),就會比較耗時了;
因此需要更改方式,觀察規(guī)律可知:f(n) = f(n-1) + f(n-2),屬于斐波那契數列。
故代碼如下:

def stairs(n):
    n1 = 1  # 一級臺階跳法數
    n2 = 2  # 二級臺階跳法數
    
    # 一級、二級臺階直接返回,三級臺階以上循環(huán)計算n級臺階前兩級跳法和
    # 例如:n = 3,n3 = n1 + n2,由于只使用兩個位置存儲數值,則需要更新n1, n2
    # n2 = n1 + n2, n1 = n2。以繼續(xù)計算n>3的情況。(最后n2即為結果)
    if n == 1:
        return n1
    elif n == 2:
        return n2
    else:
        for i in range(3, n + 1):
            n1, n2 = n2, n1 + n2
        return n2

補充:

1)遞歸函數優(yōu)點 => 定義簡單,邏輯清晰;

缺點:使用遞歸函數需要注意防止棧溢出。

遞歸調用時使用棧來保護現場和恢復現場,也很耗費資源。

2)計算機中,函數調用是通過棧(stack)這種數據結構實現的,每當進入一個函數調用,棧就會加一層棧幀,每當函數返回,棧就會減一層棧幀。由于棧的大小不是無限的,所以,遞歸調用的次數過多,會導致棧溢出。(RuntimeError: maximum recursion depth exceeded in comparison = > 運行錯誤:超出最大遞歸深度。)

python默認棧的層數為1000層

3)使用尾遞歸進行優(yōu)化:在遞歸函數返回的遞歸公式中直接調用自身本身,而不是返回計算表達式。這樣,編譯器或者解釋器就可以把尾遞歸做優(yōu)化,使遞歸本身無論調用多少次,都只占用一個棧幀,不會出現棧溢出的情況。

需要每次調用時都直接計算結果,并將每次調用的前結果暫存起來。

4)遺憾的是,大多數編程語言沒有針對尾遞歸做優(yōu)化,Python解釋器也沒有做優(yōu)化,所以,即使把遞歸函數改成尾遞歸方式,也會導致棧溢出。

尾遞歸:

# 尾遞歸計算num的階乘
def fact_iter(num, product):
    if num == 1:
        return product
    return fact_iter(num - 1, num * product)

return fact_iter(num - 1, num * product)僅返回遞歸函數本身,num - 1num * product在函數調用前就會被計算,不影響函數調用。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內容