1. 程式人生 > >leetcode 70climbing stairs 爬樓梯

leetcode 70climbing stairs 爬樓梯

題目要求(必會,高頻題)

有一個爬樓梯的任務。 需要n步才能達到頂。每次可以爬1或2步。 通過多少不同的方式登頂?
注意:給定n將是一個正整數。

示例

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

解題思路

因為每次只能走一步或者兩步, 所以在到達n層之前只可能有兩種情況:在 n-1層走一步,或者n-2層走兩步。接著,我們繼續分析,到達n-1層和n-2層同樣也是隻有兩種方法,如此下去,我們可以發現這是一個遞迴問題。

(1) 所以第一種方法我們可以根據遞迴來進行解決。

class Solution {
public:
    int climbStairs(int n) {
        if(n==1||n==
2) return n; else return (climbStairs(n-1) + climbStairs(n-2)); } };

缺點 遞迴方法就是重複計算很多,導致耗時很長,時間成指數級增長,n較大時,可能會超出時間不會AC。

(2) 動態規劃思想解決(強推!!!)
爬樓梯數目其實是一個斐波拉契數列。
當一個問題可以分解成若干重複的子問題時,動態規劃的思想非常實用:
只需要將子問題求解一次,以後再遇到,直接呼叫。
關鍵是找到一個轉移方程,由於斐波拉契數列的特點(前兩項初值1,1。從第3項開始,每一項都等於前兩項之和
Fibonacci sequence

),以及解法1中給出的遞迴式關係,我們能夠得到狀態轉換方程:
dp[i] = dp[i-1] + dp[i-2];

程式中陣列 dp[n+1] ,n為字元個數。
dp[i]表示的含義:以索引i結尾的子字串之和。

class Solution {
public:
    int climbStairs(int n) {
        int dp[n+1];
        dp[0] = 1;
        dp[1] = 1;
        for(int i=2;i<n+1;++i)
            dp[i] = dp[i-1] + dp[i-2];
        return dp[n];
    }
};

原題連結 :https://leetcode.com/problems/climbing-stairs/