力扣第 70 题:爬楼梯问题(Climbing Stairs)

力扣第 70 题:爬楼梯问题(Climbing Stairs)

一、题目描述

假设你正在爬楼梯,需要爬到第 n n n 级台阶。每次可以爬 1 1 1 2 2 2 级台阶。有多少种不同的方法可以爬到楼顶?

输入:一个正整数 n n n
输出:一个整数,表示不同的方法数。


二、解题思路

这个问题可以用 递归 + 记忆化 的方式解决,本质是一个 动态规划问题

1. 状态定义

定义 d p [ i ] dp[i] dp[i] 表示爬到第 i i i 级台阶的方法数。

2. 状态转移方程

每次可以选择爬 1 1 1 级或 2 2 2 级台阶,因此可以得到递推关系:
d p [ i ] = d p [ i − 1 ] + d p [ i − 2 ] dp[i] = dp[i-1] + dp[i-2] dp[i]=dp[i1]+dp[i2]

3. 初始条件

  • i = 1 i=1 i=1 时,只有一种方法爬到第一级:直接爬 1 1 1 级。因此, d p [ 1 ] = 1 dp[1] = 1 dp[1]=1
  • i = 2 i=2 i=2 时,有两种方法爬到第二级:爬 1 + 1 1+1 1+1 或直接爬 2 2 2。因此, d p [ 2 ] = 2 dp[2] = 2 dp[2]=2

三、递归 + 记忆化实现

我们通过递归来解决这个问题,同时使用一个数组 memo 来存储已经计算过的结果,避免重复计算。

完整代码(C 语言)

#include <stdio.h>
#include <stdlib.h>

// 递归函数,使用记忆化存储
int dfs(int n, int* memo) {
    if (n == 0) {
        return 1; // 到达楼顶的方法数
    } else if (n < 0) {
        return 0; // 无效路径
    }
    if (memo[n] != -1) {
        return memo[n]; // 如果已经计算过,直接返回
    }
    // 递归计算
    memo[n] = dfs(n - 1, memo) + dfs(n - 2, memo);
    return memo[n];
}

// 主函数
int climbStairs(int n) {
    // 动态分配 memo 数组,并初始化为 -1
    int* memo = (int*)malloc((n + 1) * sizeof(int));
    for (int i = 0; i <= n; i++) {
        memo[i] = -1;
    }

    // 调用递归函数
    int result = dfs(n, memo);

    // 释放动态内存
    free(memo);

    return result;
}

int main() {
    int n;
    printf("请输入楼梯的级数:");
    scanf("%d", &n);

    int result = climbStairs(n);
    printf("共有 %d 种不同的方法可以爬到第 %d 级台阶。\n", result, n);

    return 0;
}

四、代码详解

1. dfs 函数

递归函数负责计算从当前台阶爬到楼顶的方法数:

  • 边界条件
    • n = 0 n = 0 n=0 时,返回 1 1 1,表示当前路径有效。
    • n < 0 n < 0 n<0 时,返回 0 0 0,表示当前路径无效。
  • 记忆化查询
    • 如果 memo[n] != -1,直接返回存储的值。
  • 递归公式
    • d f s ( n ) = d f s ( n − 1 ) + d f s ( n − 2 ) dfs(n) = dfs(n-1) + dfs(n-2) dfs(n)=dfs(n1)+dfs(n2)

2. memo 的作用

memo 数组存储每一级台阶的方法数,避免了重复递归,提高了效率。

3. 主函数逻辑

  • 初始化 memo 数组为 -1
  • 调用递归函数 dfs(n, memo)
  • 释放 memo 动态内存,避免内存泄漏。

五、运行示例

输入:

请输入楼梯的级数:5

输出:

共有 8 种不同的方法可以爬到第 5 级台阶。

运行结果符合预期。


六、时间复杂度和空间复杂度分析

时间复杂度

使用记忆化递归,时间复杂度为 O ( n ) O(n) O(n),因为每一级台阶的方法数只会被计算一次。

空间复杂度

  • 递归调用栈的深度为 O ( n ) O(n) O(n)
  • memo 数组需要 O ( n ) O(n) O(n) 的空间存储结果。

总的空间复杂度为 O ( n ) O(n) O(n)


七、总结

通过递归结合记忆化存储,成功解决了爬楼梯问题。代码清晰、结构简单,并具有以下优点:

  1. 避免了重复计算,性能优于纯递归。
  2. 逻辑清晰,容易理解。

如果对递归不熟悉,也可以通过 迭代法动态规划表 实现,进一步优化空间复杂度。有关更多动态规划问题,欢迎继续关注!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值