Leetcode 70.爬楼梯——递归和反递归算法的解析


前言

写的是对leetcode《初级算法》爬楼梯题评论第一的算法的解析(❗是解析!解析!解析!❗算法不是我写的)
因为我第一次单看尾递归算法时比较懵,所以记录一下搞懂算法的过程,讲的应该算通俗易懂!
算法来自:作者:数据结构和算法
链接:https://leetcode.cn/leetbook/read/top-interview-questions-easy/xn854d/?discussion=DW6hWu


一、题目

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
示例:

输入:n = 3 输出:3
解释:有三种方法可以爬到楼顶。

  1. 1 阶 + 1 阶 + 1 阶
  2. 1 阶 + 2 阶
  3. 2 阶 + 1 阶

提示:

1 <= n <= 45

二、算法及解析

1.斐波那契数列

先说一下斐波那契数

斐波那契数列指的是这样一个数列:
1、1、2、3、5、8、13、21、34、……在数学上,斐波那契数列以如下被以递推的方法定义:
F(0)=0,F(1)=1,F(n)=F(n - 1)+F(n - 2)(n ≥ 2,n ∈ N*)

2.解决爬楼梯问题

一开始我想的是计算最多爬多少个二级台阶(n/2),然后0<=爬二级台阶的次数(t)<=n/2,然后计算有多种组合,但想想就知道太难了,所以pass掉(千万不要去想爬几个二级和一级)

以递归的思路去想这个问题:
假设n等于8,想去到第八个台阶,要么得在第七个阶梯,要么得在第六个阶梯,所以:
到达第八个阶梯=从第七个阶梯走一步上去+和第六个阶梯走两步上去

再说清楚一点:第七个阶梯 → 第八个阶梯,只能走一步,第六个阶梯 → 第八个阶,只能走两步。所以到达8个阶梯的总方法数=达到第7个阶梯的总方法+到第6个阶梯的总方法数

以此推到底可以知道:
当n等于3的时候,有f(3)=f(2)+f(1)
当n等于2的时候,共有2种跳法,f(2)=2
当n等于1:只有一种跳法,f(1)=1
再反推回去:
知道f(2)f(3)就能求出f(4),知道f(4)就能求出f(5),推到头就是结果。

递归算法

 public static int climbStairs(int n) {
        if (n <= 1)
            return 1;
        if (n < 3)
            return n;
        return climbStairs(n - 1) + 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);
    }

这里就要提到我们的斐波那契数列!
在这里插入图片描述

如何搞出计算该数列的尾递归算法,我们先画出两个指针,指针指向n=0…n,记录f(n)的值(蓝a,橙b):
在这里插入图片描述

根据F(0)=0,F(1)=1,F(n)=F(n - 1)+F(n - 2)(n ≥ 2,n ∈ N*),可以看出应该记录前两个数

当要计算n=6时,我们需要移动指针
在这里插入图片描述
可以看出来移动后指针记录的数据发生了变化:蓝a=橙b,橙b=橙b+蓝a
再联系一下尾递归代码:

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

会发现当n>1时返回调用的函数参数:a=b,b=a+b
a,b分别记录目前已知的f(n-2)和f(n-1),然后移动更新a和b的值

知道f(n-2)和f(n-1)就知道f(n),更新a和b:b记录f(n),a记录f(n-1)

还不理解的可以自己画一画:
在这里插入图片描述
到这里也知道为什么一开始的参数是(n,1,1)了


  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值