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

题记:
假设你正在爬楼梯。需要 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 阶

提示:

  • 1 <= n <= 45

题目来源:
作者:LeetCode
链接:https://leetcode.cn/leetbook/read/top-interview-questions-easy/xn854d/
来源:力扣(LeetCode)

解题方法:

一:递归写法

这题我们可以参照之前分析的青蛙跳台阶问题,其实原理是完全一样的
我们来分析一下:

  • 当n等于1的时候,只需要跳一次即可,只有一种跳法,记f(1)=1
  • 当n等于2的时候,可以先跳一级再跳一级,或者直接跳二级,共有2种跳法,记f(2)=2
  • 当n等于3的时候,他可以从一级台阶上跳两步上来,也可以从二级台阶上跳一步上来,所以总共有f(3)=f(2)+f(1);

同理当等于n的时候,总共有f(n)=f(n-1)+f(n-2)(这里n>2)种跳法。
在这里插入图片描述
所以如果我们求上到n阶有多少种,代码很简单,直接递归就行

    public static int climbStairs(int n) {
        if (n <= 1)
            return 1;
        if (n < 3)
            return n;
        return climbStairs(n - 1) + climbStairs(n - 2);
    }

转换为PHP代码为:

function climbStairs($n) {
    if($n <= 1)
        return 1;
    if($n < 3)
        return 2;
    return $this->climbStairs($n - 1) + $this->climbStairs($n - 2);
}

这种当n比较大的时候会超时,所以不推荐,但如果还想使用递归我们可以改为尾递归的方式,我们来看下代码

public static int climbStairs(int n) {
    return Fibonacci(n, 1, 1);
}

public static int Fibonacci(int n, int a, int b) {
    if (n <= 1)
        return b;
    return Fibonacci(n - 1, b, a + b);
}

转换为PHP 代码为:

function climbStairs($n) {
	$this->Fibonacci($n, 1, 1);
}

function Fibonacci($n, $a, $b){
    if($n <= 1)
        return $b;
    return $this->Fibonacci($n - 1, $b, $a + $b);
}

二:非递归

但递归由于重复计算,导致效率很差,我们来看一下,有很多重复的计算,相同的颜色表示计算多次
在这里插入图片描述
所以我们要把它改为非递归的

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

转换为PHP代码为:

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

三:非递归优化

我们看到上面的数组当前值是依赖他前面两个值的(前两个除外),我们只需要用两个临时变量即可,不需要申请一个数组

public int climbStairs(int n) {
    if (n <= 2)
        return n;
    int first = 1, second = 2, sum = 0;
    while (n-- > 2) {
        sum = first + second;
        first = second;
        second = sum;
    }
    return sum;
}

转换为PHP代码为:

function climbStairs($n) {
    if($n <= 2)
        return $n;
    $first = 1;
    $second = 2;
    $sum = 0;
    while($n-- > 2){
        $sum = $first + $second;
        $first = $second;
        $second = $sum;
    }
    return $sum;
}

四:公式计算

还可以参照公众号的这篇文章356,青蛙跳台阶相关问题,我们可以找到他的递推公式是
在这里插入图片描述
这个公式其实就是斐波那契公式,1,1,2,3,5,8,13……,
但我们这道题的前几项是1,2,3,5,8……明显比那公式少了一项,所以这里计算第n项的指数应该是n+1

public static int climbStairs(int n) {
    double sqrt = Math.sqrt(5);
    return (int) ((Math.pow((1 + sqrt) / 2, n + 1) - Math.pow((1 - sqrt) / 2, n + 1)) / sqrt);
}

转换为PHP代码为:

function climbStairs($n) {
   $sqrt = sqrt(5);
   return (pow((1 + $sqrt) / 2,$n + 1) - pow((1 - $sqrt) / 2,$n + 1)) / $sqrt;
}

方法来源:
作者:数据结构和算法
链接:https://leetcode.cn/leetbook/read/top-interview-questions-easy/xn854d/?discussion=DW6hWu
来源:力扣(LeetCode)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 假设你正在爬楼梯需要n你才能到达楼顶。每次你可以爬1或2个台。那么你有多少种不同的方法可以爬到楼顶呢? 答案是斐波那契数列。斐波那契数列是指:1、1、2、3、5、8、13、21、34、……,即第一项和第二项为1,从第三项开始,每一项都等于前两项之和。 因为每次只能爬1或2个台,所以爬到第n的方法数就等于爬到第n-1和爬到第n-2的方法数之和。而爬到第1和第2的方法数都是1,所以可以得到递推公式: f(n) = f(n-1) + f(n-2) 其中f(n)表示爬到第n的方法数。根据递推公式,可以用递归或循环的方式求解斐波那契数列,从而得到爬楼梯的方法数。 ### 回答2: 这个问题属于经典的动态规划问题,我们可以用递推的方法来解决。 当 n=1 时,显然只有一种方法可以爬到楼顶,也就是一步一步爬。 当 n=2 时,有两种方法可以到达楼顶,一种是一次爬两步,另一种是先爬一步,再爬一步。 当 n>2 时,我们假设到达第 i 的方法有 f(i) 种。那么到达第 i 可以分为两种情况: 1. 在第 i-1 时向上爬一步。 2. 在第 i-2 时向上爬两步。 因此,f(i) = f(i-1) + f(i-2)。 最后只需要算出 f(n) 就可以知道到达楼顶的不同方法了。 我们可以用一个数组来存储 f(i)。初始时,f(1)=1,f(2)=2。 然后从 f(3) 开始,每个 f(i) 都等于前面两项的和,也就是 f(i-1) + f(i-2)。 最后返回 f(n) 就是到达楼顶的不同方法数了。 总结一下,假设需要爬 n 楼梯才能到达楼顶,你有 f(n) 种不同的方法可以爬到楼顶。 其中,f(1)=1,f(2)=2,f(i)=f(i-1) + f(i-2) (i>=3)。 ### 回答3: 我们可以用动态规划的思想来解决这个问题。设 f(i) 为到第 i 时爬楼的方法数目,因为每一步都只能向上爬 1 或 2 ,所以到达第 i 的方法只有两种:从第 i-1 向上爬 1 ,或者从第 i-2 向上爬 2 。所以我们可以得到状态转移方程: f(i) = f(i-1) + f(i-2) 同时,为了递推出 f(i) 的值,我们还需要初始化 f(1) 和 f(2) 的值。因为到第 1 只有一种方法,我们有:f(1) = 1;到第 2 有两种方法,我们有:f(2) = 2。所以最终的思路就是:从第 3 开始递推,每次用上面的状态转移方程求出 f(i) 的值,直到求出 f(n) 的值为止。 以下是代码实现: int climbStairs(int n) { int f[n+1]; memset(f, 0, sizeof(f)); f[1] = 1; f[2] = 2; for (int i = 3; i <= n; i++) { f[i] = f[i-1] + f[i-2]; } return f[n]; } 算法的时间复杂度为 O(n),空间复杂度为 O(n),可以满足数据规模限制。因此,我们可以用这个算法来计算爬楼梯的方法数目。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值