從本題中我們可以學到包含重複子問題,可以採用記憶化的方式,復用計算後的值;並用動態規劃的思想,找到動態轉移方程,採用迴圈實現。
題目描述:
題目:假設我們需要爬乙個樓梯,這個樓梯一共有 n 階,可以一步跨越 1 個或者 2 個台階,那麼爬完樓梯一共有多少種方式?
示例:
輸入:2有2種方式可以爬樓梯,跳1+1階,跳2階輸出:2
示例:
輸入:3有3種方法爬樓梯,跳1+1+1階,1+2階,2+1階;輸出:3
推理:
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度的螺旋狀樓梯是一種能真實節約空間的樓梯修建方法,...