70. 爬楼梯,记忆递归以及递归的几个等价写法

问题

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

每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?

示例 1:
输入:n = 2
输出:2
解释:有两种方法可以爬到楼顶。

  1. 1 阶 + 1 阶
  2. 2 阶

分析

dp入门题,递归,记忆递归,递推。

一、递推

class Solution {
public:
    int f[50];
    int climbStairs(int n) {
        f[0] = 1;
        f[1] = 1;
        for (int i = 2; i <= n; i++) {
            f[i] = f[i-1] + f[i-2];
        }
        return f[n];
    }
};

二、递归,超时,21/45

class Solution {
public:
    int dfs(int x) {
        if (x == 0 || x == 1) {return 1;}
        return dfs(x-1) + dfs(x-2);
    }
    int climbStairs(int n) {
        return dfs(n);
    }
};

三、记忆递归

class Solution {
public:
    int mem[50];
    int dfs(int x) {
        if (mem[x] != -1) {return mem[x];}
        if (x == 0 || x == 1) {return 1;}
        int s = 0;
        s = dfs(x-1) + dfs(x-2);
        mem[x] = s;
        return s;
    }
    int climbStairs(int n) {
        memset(mem, -1, sizeof mem);
        return dfs(n);
    }
};

递归改为记忆递归的方法:

  • 在递归出口前后各加一句、之后的都赋值s、s赋值记忆数组、返回s

补充几个递归的写法,加深理解

对于每个子状态的结果,可以用返回值,参数,全局变量来记录,三种方法等价。返回值最简单,其他的这里给出写法。

  1. 不带返回值的递归
class Solution {
public:
    void dfs(int x, int& ans) { // 注意这里是引用
        if (x == 0 || x == 1) {ans = 1; return ;}
        int a = 0, b = 0;
        dfs(x-1, a);
        dfs(x-2, b);
        ans = a+b;
    }
    int climbStairs(int n) {
        memset(f, -1, sizeof f);
        int res = 0;
        dfs(n, res);
        return res;
    }
};
  1. 全局变量
class Solution {
public:
    int res = 0;
    void dfs(int x) {
        if (x == 0 || x == 1) {res = 1; return ;}
        int a = 0, b = 0;
        dfs(x-1); a = res;
        dfs(x-2); b = res;
        res = a+b;
    }
    int climbStairs(int n) {
        dfs(n);
        return res;
    }
};

综上,还是返回值更好理解。

posted @ 2025-06-19 18:03  saulstavo  阅读(14)  评论(0)    收藏  举报