《LeetCode之每日一题》:111.爬楼梯之变

爬楼梯之变


题目链接: 爬楼梯官方题解下方的评论区
爬楼梯解答

有关题目

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。

每次你可以爬 12 个台阶。且不能连续跳两个台阶

你有多少种不同的方法可以爬到楼顶呢?

注意:给定 n 是一个正整数。

题解

法一:动态规划

思路:
定义:f(x) 表示爬到第 x 级台阶的方案数
g(x, 1) 表示爬到第 x 级台阶并且最后一步跨越一个台阶的方案数
g(x, 2) 表示爬到第 x 级台阶并且最后一步跨越了两个台阶的方案数

则有: f(x) = g(x, 1)+g(x,2)g(x, 1) = f(x-1)g(x, 2) = g(x-2, 1)
// 最后一步跨越了两步,那么上一步只能跨越一步

最终得到一下方程式: f(x) = g(x, 1) + g(x, 2) = f(x-1)+g(x-2, 1) = ( g(x-1, 1)+g(x-1, 2) )+g(x-2, 1) = g(x-1, 1)+g(x-1, 2)+g(x-2, 1)

代码一:



int climbStairs(int n){
    int dp[n + 1][3];
    dp[1][1] = 1, dp[2][1] = 1, dp[2][2] = 1;
    for (int i = 3; i <= n; i++){
        dp[i][1] = dp[i - 1][2] + dp[i - 1][1];
        dp[i][2] = dp[i - 2][1];
    }
    return dp[n][1] + dp[n][2];
}

代码二:



int climbStairs2(int n){
    // one[i] 最后一次是爬 1 层楼梯到达楼梯 i 
	// two[i] 最后一次是爬 2 层楼梯到达楼梯 i 的方法数
    int one[n + 1], two[n + 1];
    one[0] = 1, two[0] = 1;
    one[1] = 1, two[1] = 0;

    for (int i = 2; i <= n; i++){
        one[i] = one[i - 1] + two[i - 1];
        two[i] = one[i - 2];
    }
    return one[n] + two[n];
}

时间复杂度:O(n)
空间复杂度:O(n)
法二:动态规划优化

思路1:
结合执行树会更快理解:
                           6
                      /            \
                     5              4
                /        \         /
               4          3       3
           /       \     /      /   \
          3         2   2      2     1
        /  \       /   / \    / \   /
       2    1     1   1   0  1   0 0
      / \   /    /   /      /
     1   0 0    0   0      0
    /
   0
   其中左节点为权 1,右节点为权 2,很明显,问题的解为树的非空叶节点个数。

在这里插入图片描述

思路二:
假设:
f(x) 表示爬到第 x 级台阶的方案数, 
g(x, 1) 表示爬到第 x 级台阶并且最后一步跨越一个台阶的方案数, 
g(x, 2) 表示爬到第 x 级台阶并且最后一步跨越了两个台阶的方案数。

由 :
f(x) = g(x, 1)+g(x,2)g(x, 1) = f(x-1)g(x, 2) = g(x-2, 1) // 最后一步跨越了两步,那么上一步只能跨越一步

f(x) = g(x, 1) + g(x, 2) 
      = f(x-1) + g(x-2, 1) 
      = f(x-1) + f((x-2)-1)
      = f(x-1) + f(x-3)

代码片段:

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

时间复杂度:O(n)
空间复杂度:O(n)
法三:滚动数组

1 1 2 3 4
1 2 3 

int climbStairs(int n){
    if (n <= 2) return n;
    int pppre = 1, ppre = 1, pre = 2;//012
    int ans = 0;
    for (int i = 3; i <= n; i++){
        ans = pppre + pre;
        pppre = ppre;
        ppre = pre;
        pre = ans;
    }
    return ans;
}

时间复杂度:O(n)
空间复杂度:O(1)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值