動態規劃走樓梯 Leetcode 70 爬樓梯

2021-10-16 11:03:55 字數 3237 閱讀 7754

從本題中我們可以學到包含重複子問題,可以採用記憶化的方式,復用計算後的值;並用動態規劃的思想,找到動態轉移方程,採用迴圈實現。

題目描述:

題目:假設我們需要爬乙個樓梯,這個樓梯一共有 n 階,可以一步跨越 1 個或者 2 個台階,那麼爬完樓梯一共有多少種方式?

示例:

輸入:2

輸出:2

有2種方式可以爬樓梯,跳1+1階,跳2階

示例:

輸入:3

輸出:3

有3種方法爬樓梯,跳1+1+1階,1+2階,2+1階;

推理:

1階樓梯,跳1階,有1種方法;

2階樓梯,跳1+1階,跳2階,有2種方法;

3階樓梯,跳1+1+1階,1+2階,2+1階,有3種方法;

4階樓梯,跳1+1+1+1階,1+2+1階,1+1+2階,2+1+1階,2+2階,有5種方法;

如果要跳 n 階台階,最後一步動作可以是上1階,也可以上2階,可以轉化為:

以上4階樓梯舉例,選擇最後上 1 階到達,則為 1 + (1+1+1)階,1 + (2+1)階,1 + (1+2)階,括號中的方法,正好是上 3 階樓梯的方法;選擇最後上 2 階到達,則為 2 + (1+1)階,2 + (2)階,括號中的方法,正好是上 2 階樓梯的方法。

所以最後上 n 階樓梯可以得出:

fn(n) = fn(n - 1) + fn(n - 2)

類似是 斐波那契數列 的形式了,可以用遞迴進行實現。

遞迴實現**:

var climbstairs = function(n) ;console.log(climbstairs(4));  // 5console.log(climbstairs(20));  // 10946
可以畫個圖具象表示:

遞迴演算法的時間複雜度怎麼計算?用子問題個數乘以解決乙個子問題需要的時間。

首先計算子問題個數,即遞迴樹中節點的總數。顯然二叉樹節點總數為指數級別,所以子問題個數為 o(2^n)

然後計算解決乙個子問題的時間,在本演算法中,沒有迴圈,只有 f(n - 1) + f(n - 2) 乙個加法操作,時間為 o(1)。

所以,這個演算法的時間複雜度為二者相乘,即 o(2^n),指數級別,隨著 n 越大,複雜度會越來越高。

在以上遞迴過程中,會有很多重複的計算。例如計算上 5 階梯的方法,則需要計算上 4 階梯的方法,和上 3 階梯的方法;要計算上 4 階梯的方法,則需要計算上 3 階梯的方法,和上 2 階梯的方法。

計算上 3 階梯的方法在第一次計算後,之後又要重新計算,這樣會造成重複計算。

這是乙個典型的重疊子問題,怎麼讓重複計算的結果更高效地利用呢?

可以採用記憶化遞迴的方式,把已經計算好的結果快取起來,以備遇到已經計算過的數字,可以直接使用,不再耗時計算。

記憶化遞迴**實現:

const climbstairs = function(n)   // 快取計算過的值  const loop = (n) =>     return cache[n]  }  return loop(n)};console.log(climbstairs(4));  // 5console.log(climbstairs(20));  // 10946
從上面看出,定義物件來儲存已計算好的結果,key值為上的階梯數,value值為階梯計算後的方法數, 每個階梯只需要計算一次,可以達到o(n)的時間複雜度。

這種方法是自頂向下計算,從乙個規模較大的原問題fn(20)開始,一步步拆分為越來越小的規模計算,直到最後不能拆分為止的fn(1)fn(2)為止,然後逐層返回結果。

還有一種方式是自底向上計算,先從問題最小規模的fn(1)fn(2)開始,不斷的擴大規模,直到推導出最終原問題fn(20)的值,便得到最終的結果。

自底向上屬於動態規劃的思路,可以使用迴圈完成。

動態規劃**:

const climbstairs = function(n)   return result[n]};console.log(climbstairs(4));  // 5console.log(climbstairs(20));  // 10946
在動態規劃中有乙個 動態轉移方程 的概念,實際上就是描述問題結構的數學形式:

聽起來很高深,實際上可以把fn(n)當做乙個狀態,這個狀態是由狀態fn(n-1)fn(n-2)相加轉移而來的,通過不斷的迴圈,轉態不斷的轉移到要求值得n上,僅此而已。

上面的**還可以進一步簡化,當前的狀態只和兩個狀態相關,記錄兩個狀態便能夠得到另乙個狀態,在迴圈過程中記錄兩個狀態即可。

簡化**:

const climbstairs = function(n)   return current};console.log(climbstairs(4));  // 5console.log(climbstairs(20));  // 10946
總結:以上是對這道題的解析發現,可以使用斐波那契額的思路,採用遞迴的方式實現,時間複雜度在o(2^n),成指數級上公升;

又從中看出有重疊子問題,採取記憶化遞迴,將重複計算的值快取起來,以免多次計算,時間複雜度降到了o(n)

後有採用了動態規劃的方式,得到轉移方程式,採用迴圈的方式實現。

動態規劃走樓梯

main.cpp 動態規劃走樓梯 created by liujan on 11 18 14.問題描述 乙個樓梯有20級,每次走1級或2級,從底走到 頂一共有多少種走法?分析 假設從底走到第n級的走法有f n 種,走到第n級 有兩個方法,乙個是從第 n 1 級走1步,另乙個是從第 n 2 級走2步,...

動態規劃走樓梯 leetcode 70 爬樓梯

力扣 leetcode cn.com 題目描述 假設你正在爬樓梯。需要 n 階你才能到達樓頂。每次你可以爬 1 或 2 個台階。你有多少種不同的方法可以爬到樓頂呢?注意 給定 n 是乙個正整數。示例 1 輸入 2 輸出 2 解釋 有兩種方法可以爬到樓頂。1.1 階 1 階 2.2 階 示例 2 輸入...

動態規劃走樓梯 室內樓梯款式大全

樓梯樣式普遍的有直梯 折梯 旋梯等。安全性為主的家中,能夠選擇直梯 折梯等傳統式構造,樓梯正下方空間樣子標準可作收納整理之作 考慮到裝飾藝術 時尚潮流感的家中則能夠選擇轉動樓梯,梯步還可以應用更美觀大方的夾層玻璃梯步。下面詳解一下。1.螺旋狀 180度的螺旋狀樓梯是一種能真實節約空間的樓梯修建方法,...