【算法】爬楼梯-初步动态规划理解

776 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第9天,点击查看活动详情

题目 爬楼梯

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

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

思路

这道题看起来是简单难度, 但是对没有接触过动态规划问题的友友们来说, 看起来绝对一脸懵, 我就是这样!

而且官方的题解给的很简略, 具体上代码也几乎没有注释, 很难让人理解! 下面让我们用最直白的语言说一下该怎么写这道题:

  1. 1阶楼梯1种方法
  2. 2阶楼梯2种方法: 爬两个1阶或一次爬2阶
  3. 3阶楼梯几种方法?

你可以直接站在第三阶楼梯上看, 在你上到第三阶楼梯的那最后一步只有两种可能, 你最后一步爬了两级楼梯, 或最后一步爬了一级楼梯

  • 你爬了一级, 就说明你是站在第二阶楼梯的基础上爬上来的
  • 你爬了两级, 就说明你是站在第一阶楼梯的基础上爬上来的
  • 所以 3阶楼梯的爬法 = 爬到2阶楼梯的爬法总数 + 爬到1阶楼梯的爬法总数

这样一步步推,

n阶楼梯的爬法 = 爬到n-1阶楼梯的爬法总数 + 爬到n-2阶楼梯的爬法总数

按这个理解上代码

代码

  • step数组就是n阶楼梯有step[n]种爬法的意思, 每阶楼梯的爬法都记录在数组中, 下一阶楼梯的爬法就很轻易的可以通过当前数组元素的前两个元素之和求出来::
class Solution {
    public int climbStairs(int n) {
        int[] steps = new int[n+1];
        steps[0] = 1;
        steps[1] = 1;
        for(int i=2; i<=n; i++){
            steps[i] = steps[i-1]+steps[i-2];
        }
        return steps[n];
    }
}

说一下这里为什么step[0]=1,

  • 按照n阶楼梯有step[n]种爬法的意思, step[0]的数值本身并没有什么意义, 但是将step[0]设置为1, 可以从i=2开始很方便的取到前两个数组元素的值之和=2, 不用我们额外写判断了, 起到了简化代码的作用.

优化

提交代码, 发现这个内存消耗的排行不行呀, 怎么优化? image.png 再探再报, 看看这个循环:

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

发现我们其实一直用到的是当前数组元素的值和他前两个元素的值, 其他元素的值压根用不到, 那么我们我们扣一点, 全程是可以用3个变量来取代这个step数组的.

这三个变量分别是:

  • 代表当前第i阶楼梯爬法的c(current)
  • 代表当前楼梯往前两个楼梯爬法的f(first)
  • 代表当前楼梯往前一个楼梯爬法的s(second)

image.png

class Solution {

    public int climbStairs(int n) {
        int f = 1;
        int s = 1;
        int c = 1;
        for(int i=2; i<=n; i++){
            c = f + s;
            f = s;
            s = c;
        }
        return c;
    }
    
}

总结

做题的时候要坚信, 不是你不行, 是他们讲的不行!