1. 程式人生 > >【LeetCode & 劍指offer刷題】動態規劃與貪婪法題1:70 Climbing Stairs

【LeetCode & 劍指offer刷題】動態規劃與貪婪法題1:70 Climbing Stairs

【LeetCode & 劍指offer 刷題筆記】目錄(持續更新中...)

70. Climbing Stairs

You are climbing a stair case. It takes   n   steps to reach to the top. Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top? Note:   Given  
n   will be a positive integer. Example 1: Input: 2 Output: 2 Explanation: There are two ways to climb to the top. 1. 1 step + 1 step 2. 2 steps Example 2: Input: 3 Output: 3 Explanation:
There are three ways to climb to the top. 1. 1 step + 1 step + 1 step 2. 1 step + 2 steps 3. 2 steps + 1 step   //問題:爬樓梯(每次只能爬1步或者2步) //分析:具有最優子結構和重疊子問題的兩點特性,可以用動態規劃方法 //暴力法:遞迴分解climbStairs(i,n)=(i+1,n)+climbStairs(i+2,n),由於存在很多重複子問題,效率很低,時間複雜度為O(2^n)(遞迴二叉樹結點數)
/* //方法一:帶備忘的自頂向下法(O(n),O(n)) //分解問題:climbStairs(i,n)=(i+1,n)+climbStairs(i+2,n),i為當前的步子,n為目標的步子 class Solution { public:     int climbStairs(int n)     {         vector<int> memo(n);         return climb_stairs(0, n, memo); //遞迴     }     int climb_stairs(int i, int n, vector<int>& memo)     {         if(i>n) return 0; //後面分解的時候有i+1和i+2,故有可能出現i>n的情況         if(i==n) return 1; //初始值         if(memo[i] > 0) return memo[i];//已經計算的不必重新計算         memo[i] = climb_stairs(i+1, n, memo) + climb_stairs(i+2, n, memo);//每一次只能爬一步或兩步         return memo[i];     } };*/ //方法二:自底向上法(O(n),O(n)) //通項公式:可以從座標(i-1)到座標i,也可以從座標(i-2)到座標i, //故有dp[i]=dp[i−1]+dp[i−2],dp[i]表示到座標i的走法,所以可以從按問題規模從小到大計算,這樣就不會計算重複問題了 (可以寫出遞推公式,自上而下分析,自下而上解決) //思路:考慮到座標n,有兩種情況,在n-1級臺階上往上跳1級,在n-2級臺階上往上跳2級,故得an = an-1 + an-2,可以推廣到其他位置 class Solution { public :     int climbStairs ( int n     {         if(n <= 0) return 0;         if ( n = = 1 ) return 1 ; //因為通項公式中最少須有兩個初始值           vector < int > dp ( n + 1 ); //初始化為0         dp [ 0 ] = 1 ; dp [ 1 ] = 1 ;         for ( int i = 2 ; i <= n ; i ++) dp [ i ] = dp [ i - 1 ] + dp [ i - 2 ]; //假設dp[0]=1,則從dp[2]開始滿足通項公式         return dp [ n ];             } }; //方法三:斐波那契數列(O(n),O(1)) 計算時只儲存三個數,故可節省空間(方法二也可以做此優化) //方法四:Binets Method(O(logn),O(1)) [[Fn+1 Fn], [Fn Fn-1]] = [[1 1], [1 0]]^n   延伸1: (變態跳臺階)     如果這個青蛙可以跳1級、2級...n級,則跳上n級臺階有多少種跳法 思路:跳到n級臺階,an = an-1 + an-2 +....a1 +a0 (a0 = 1,表示從起點一次性跳n級,a1 =1, a2 =2),由數學歸納法可以證明an = 2^(n-1)   延伸2:矩形覆蓋      我們可以用2*1的小矩形橫著或者豎著去覆蓋更大的矩形。請問用n個2*1的小矩形無重疊地覆蓋一個2*n的大矩形,總共有多少種方法?   /* 問題:矩形覆蓋 方法:動態規劃 f(n)表示2*n的矩形的覆蓋方法 f(n)可以是2*(n-1)的矩形加一個豎著放的2*1的矩形或2*(n-2)的矩形加2橫著放的, 故遞推公式為:f(n)=f(n-1)+f(n-2) 另外,f(1)=1,f(2)=2,為方便起見,假設f(0) = 1 */ class Solution { public :     int rectCover ( int n )     {         if ( n <= 0 ) return 0 ;         if ( n == 1 ) return 1 ;                 vector < int > dp ( n + 1 );         dp [ 0 ] = dp [ 1 ] = 1 ;         for ( int i = 2 ; i <= n ; i ++)             dp [ i ] = dp [ i - 1 ] + dp [ i - 2 ];                 return dp [ n ];     } };