题目
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
示例 1:
输入:n = 2 输出:2 解释:有两种方法可以爬到楼顶。 1. 1 阶 + 1 阶 2. 2 阶
示例 2:
输入:n = 3 输出:3 解释:有三种方法可以爬到楼顶。 1. 1 阶 + 1 阶 + 1 阶 2. 1 阶 + 2 阶 3. 2 阶 + 1 阶
思路
爬 0 层和爬 1 层都只有一种情况, 但是爬两层有两种:一次爬一层一共爬两次、一次爬两层一共爬一次,爬三层有三种:一次爬一层一共爬三次、先爬一层再爬两层一共爬两次、先爬两层再爬一层一共爬两次。所以 f(0) = 1, f(1) = 1, f(2) = 2, f(3) = 3, f(4) = 5。规律是 f(n) = f(n-1) + f(n-2),因为爬到第 n 阶有两种情况,分别是站在第 n-1 阶爬一层和站在第 n-2 阶爬两层,所以就是 f(n-1) 和 f(n-2)的和。
方法一 官方题解的动态规划
时间复杂度O(n),空间复杂度O(1),运行用时 0ms,击败100%,内存消耗5.46MB,击败36.61%。
int climbStairs(int n) {
    int p = 0, q = 0, r = 1;
    for (int i = 1; i <= n; ++i) {
        p = q;
        q = r;
        r = p + q;
    }
    return r;
}
方法二 快速幂
看不懂也想不到

方法三 通项公式
这个更想不到了
 
 
方法四 递归
本质上和方法一相同。直接递归会超时,需要“记忆递归”,下面是题解里的代码。执行用时 0 ms,击败100%,内存消耗 5.8 MB,击败 5.12%. calloc函数会把分配的内存置为0,而 malloc函数不会。
int _climb(int n, int *arr)
{
    if (arr[n] != 0 ) return arr[n];
    arr[n] = _climb(n-1, arr) + _climb(n-2, arr);
    return arr[n];
}
int climbStairs(int n){
    //终止情况
    if ( n <  0 ) return 0;
    if ( n <= 2) return n;
    int *arr = (int*)calloc(n+1, sizeof(int));
    arr[1] = 1;
    arr[2] = 2;
    return _climb(n , arr);
}最后记录一下自己写的垃圾代码
int climbStairs(int n) {
    if(n == 1)
    	return 1;
    else{
    	int a = 1;
    	int b = 1;
    	int i = 2;
    	int res = 1;
    	while(i <= n){
    		res = a + b;
    		a = b;
    		b = res;
    		i++;
		}
		return res;
	}
}



















