递归--斐波那契数(1)

本文讲述了如何通过数学方法而非递归求解斐波那契数列的问题,重点在于理解数列的线性组合性质,并给出了一个逐步推导和编程实现的过程,强调思考过程的重要性。
摘要由CSDN通过智能技术生成

问题:斐波那契数 (通常用 F(n) 表示)形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是:

F(0) = 0,F(1) = 1
F(n) = F(n - 1) + F(n - 2),其中 n > 1

给定 n ,请计算 F(n) 。

  虽然题目明显是递归题,但作者首先不考虑这个要求,优先写出答案。分析问题得,这是一道看起来简单的加法题,关于函数的加法题,其中函数为y = F(n),如果我们能够通过递推表达式推出函数映射关系F就可以直接算出F(n),故我们下一步是找出函数的映射关系。
题目类型:函数、加法、递推

  如此一来,这题就变成数学题。数学中算出递推式表达式相信大家都推过,利用1.初值F(0)、F(1) 2.递推关系来推出后面的值以及整体表达式。故我们先推几个从局部中寻找整体的关系。

F(0) = 0
F(1) = 1
F(2) = F(1) +F(0) = 1
F(3) = F(2) + F(1) = F(1) + F(0) + F(1) = 2
F(4) = F(3) + F(2) = F(1) + F(0) + F(1) + F(1) + F(0) = 3 //后面展开省略
F(5) = F(4) + F(3) = 5

  容易看出当n>2时,F(n)是通过F(0)、F(1)的线性组合构成,反过来就是F(0)、F(1)的线性组合可以得到F(n)。题目所给的递推公式是F(n) = F(n-1)+F(n-2),但作者觉得写成F(n-1)+F(n-2) = F(n)才更好理解它是递推式,利用现有信息F(n-1)与F(n-2)去推未知信息F(n),这是推动的关键。(这里作者想表示的核心思路是F(n)是如何构成的,它形成的根本在哪里,不要在标准答案一层层递归中迷失方向)(以及读者如果无法理解作者为何想倒过来说也没有影响,这只是当初作者对于表达式的困惑点)

如果觉得上面推到出线性组合过程如教材答案一样容易看出,这里再进一步解释。
F(2)是F(1)与F(0)的线性组合
F(3)也是F(1)与F(0)的线性组合
F(4) = F(2) + F(3)是F(2)与F(3)的线性组合,线性组合叠加,可以推出F(4)为F(1)与F(0)的线性组合。

(可跳过)这里具体说一下上面等式作者为何觉得倒过来更方便理解,因为在等式运算中结果都是写在右边,例如:1+2=3。如题目中这样一般都是方程,例如:x=1+2,左边是右边的结果。其本质都是一样的,只是作者觉得等式运算比解方程方便理解一些,毕竟方程可是小学四年级才学的!	

  网上有关于表达式F(n)具体如何直接推的,作者数学不好,在这里就不献丑直接跳过了。
  可以发现推出这个具体表达式过程十分复杂,更甚于有推不出表达式的我们又该怎么办?不会写了,反正当初作者学的时候看答案都不会的,看答案一直搁那递归递归着就出来了,算着好像又是那回事,但就是不太理解,迷失在了其具体实现步骤当中。
  利用数学的方法我做不到,那只能当傻子一步一步慢慢推上去了。
  看这段后面我希望你至少了解了它们具体是如何的,F(n)是F(1)与F(0)的线性组合。回过头来,我们其实只需要找出其线性组合的参数是多少?(F(n) = kF(1) + lF(0),其中k与l是多少)本问题最难的部分,前面我一直都在不仔细考虑中间的具体递推公式,F(n) = F(n-1)+F(n-2),这里还是逃不开方程了,毕竟用一个未知数代替杂七杂八的东西太方便了,先举个简单例子。

F(0) = 0													x = 0
F(1) = 1						---->						y = 1
F(2) = F(0) + F(1) 											z = x + y
F(3) = F(2) + F(1) 											w = z + y 

  可知我们在利用F(n-1)+F(n-2)向前推时不断更新F(n-1)与F(n-2)的值,从而不断推出了其线性组合的具体参数。希望看到这初学者能自己写完。
  代码如下:

class Solution {
public:
    int fib(int n) {
        int sum = 0;
        int beforeNum = 0; //f(n-1)
        int moreBeforeNum = 0; //f(n-2)
        for(int i = 1; i <= n; i++){ //方便理解,注意i从1开始,f(i)
            if(i == 1)
            {
                beforeNum = 1;
                sum = beforeNum + moreBeforeNum;    
                
            }
            else 
            {
                sum = beforeNum + moreBeforeNum; //f(n) = f(n-1) + f(n-2)
                moreBeforeNum = beforeNum; //f(n-2)替换为新的
                beforeNum = sum; //f(n-1)替换为新的
            }     
        }
        return sum;
    }
};

  这样我们最后是利用一步一步递推写出了这一题,不符合出题者一开始的想法,不过能过是重要的,在下一节我将先说一下对递归的看法,最后再给答案。

  闲聊:希望特别是初学者能够先自己想方法写出来,即使那并不是“正确”答案,思考过程比答案更加重要。这节中间可能写的不太好理解,如果有困惑务必告诉我,我有点抓不准当时的困惑点了。
  文章不足之处,不方便理解处待指正。
力扣题目链接:https://leetcode.cn/problems/fibonacci-number/

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值