題目
假設(shè)你正在爬樓梯,需要n步你才能到達頂部。但每次你只能爬一步或者兩步,你能有多少種不同的方法爬到樓頂部?
樣例
比如n=3,1+1+1=1+2=2+1=3,共有3中不同的方法,返回 3
分析
典型的動態(tài)規(guī)劃問題。
我們假設(shè)到達第n級臺階的方法數(shù)為f(n),那么最后一步的時候,我們有兩種選擇,一是選擇爬一步,那么這時候的方法數(shù)就是f(n-1),另一種選擇是選擇爬兩步,方法數(shù)f(n-2).所以通過這個我們就可以得出f(n)的狀態(tài)轉(zhuǎn)移方程:
f(n)=f(n-1)+f(n-2)
顯然看到這里,我們可以利用遞歸求解這個問題。
public class Solution {
/**
* @param n: An integer
* @return: An integer
*/
public int climbStairs(int n) {
// write your code here
if (n == 0 || n == 1) return 1;
if (n < 0) return 0;
return climbStairs(n - 1) + climbStairs(n - 2);
}
}
climb.PNG
提交結(jié)果告訴我們超時了。所以我們不能用遞歸,需要采用效率更高的算法。
其實這類似于斐波那契數(shù)列,我們直接利用一個數(shù)組來記錄f(n)就可以了。
public class Solution {
/**
* @param n: An integer
* @return: An integer
*/
public int climbStairs(int n) {
// write your code here
if (n == 1 || n==0) return 1;
int[] f = new int[n+1];
f[0] = 1;
f[1] = 1;
for(int i=2;i<=n;i++)
f[i] = f[i-1] + f[i-2];
return f[n];
}
}
這種解法可以正確通過!
但我們可以更進一步優(yōu)化算法,只采用兩個變量即可
f(n) = f(n-1)+f(n-2)
f(n-1) = f(n) - f(n-2)
利用這個關(guān)系,
one = one + zero;
zero = one - zero;
代碼
public class Solution {
/**
* @param n: An integer
* @return: An integer
*/
public int climbStairs(int n) {
// write your code here
int one = 0;
int two = 1;
while(n>0) {
two=one+two;
one=two-one;
n--;
}
return two;
}
}
小結(jié)
爬樓梯是一個典型的一維動態(tài)規(guī)劃問題