有限制的楼梯攀登 | 豆包MarsCode AI刷题

88 阅读3分钟

题目解析

本文是一篇题解分享,对应题目是AI刷题板块的中等题-《有限制的楼梯攀登》。 问题简述如下:

有一座非常高的楼梯,每次可以选择走一步或两步,但不能连续走两步。求解有多少种不同的方法可以从楼梯的底部走到顶端。

思路分析

本题是一个典型的动态规划类题目。走到第i级阶梯的方法与走之前阶梯的方法直接相关。比如走到第i级阶梯是一步上来的,那么走到第i- 1级阶梯可以走两步,也可以走一步。如果走到第i级阶梯是两步上来的,那么上一次落脚应该在第i- 2级阶梯,且到第i - 2级阶梯时不能是两步上来的。

代码逻辑

根据前文的分析,可以得到状态转移方程如下

// dp[i][0] 表示走到第i级阶梯时是走一步
// dp[i][1] 表示走到第i级阶梯时是走两步
dp[i][0] = dp[i - 1][0] + dp[i - 1][1]
dp[i][1] = dp[i - 2][0]

另外,数组的初始化设置如下

// 到达第0级阶梯时不需要迈步
dp[0][0] = 0; 
dp[0][1] = 0;
// 到达第1级阶梯时只有一种可能,即从第0级阶梯走一步上来
dp[1][0] = 1;
dp[1][1] = 0;
// 到达第2级阶梯时有两种可能,可以从第1级阶梯走一步上来,也可以从第二级阶梯走两步上来
dp[2][0] = 1;
dp[2][1] = 1;

完整代码

完整的代码如下

public static int solution(int n) {
    if(n == 1 || n == 2){
        return n;
    }
    // 基本思路:动态规划
    // dp[i][0] - 走到i跨了一级 dp[i - 1][0] + dp[i - 1][1]
    // dp[i][1] - 走到i跨了两级 dp[i - 2][0]
    int[][] dp = new int[n + 1][2];
    dp[0][0] = 0;
    dp[0][1] = 0;
    dp[1][0] = 1;
    dp[1][1] = 0;
    dp[2][0] = 1;
    dp[2][1] = 1;
    for(int i = 3; i < n + 1; i++){
        dp[i][0] = dp[i - 1][0] + dp[i - 1][1];
        dp[i][1] = dp[i - 2][0];
    }
        

    return dp[n][0] + dp[n][1];
}

知识总结

  • 动态规划:

    • 动态规划的核心思想是将问题分解为子问题,并通过存储子问题的解来避免重复计算。
    • 动态规划通常用于解决具有重叠子问题和最优子结构性质的问题。
  • 状态定义与转移:

    • 在动态规划中,状态定义是关键。我们需要明确每个状态的含义以及如何从上一个状态转移到当前状态。
    • 状态转移方程是动态规划的核心,它描述了如何从已知状态推导出新的状态。
  • 初始条件:

    • 动态规划问题通常需要初始条件来启动计算。初始条件是已知的最简单情况的解。
  • 时间复杂度与空间复杂度:

    • 动态规划的时间复杂度通常与状态数和状态转移的复杂度相关。
    • 空间复杂度通常与存储状态所需的额外空间相关。

学习计划

动态规划类题目是比较常见的算法题目类型。初学者可以先通过简单的动态规划类题目入手,通过阅读题解或者观看视频来形成做题的规范。比如先从leetcode中找到动态规划类的题目,然后阅读官方题解或者比较优秀的个人题解。前期可以copy题解的代码,后面要逐步形成自己的做题思路。

工具运用

  1. 刷题网站:codeforce / leetcode / 稀土掘金AI刷题等
  2. 优秀题解:leetcode官方题解 / 灵茶山艾府等
  3. AI:豆包Marscode AI / ChatGPT等