【JZ10 斐波那契数列】

描述

大家都知道斐波那契数列,现在要求输入一个正整数 n ,请你输出斐波那契数列的第 n 项。
斐波那契数列是一个满足

在这里插入图片描述
的数列。数据范围: 1 ≤ n ≤ 40
要求:空间复杂度 O(1),时间复杂度 O(n) ,本题也有时间复杂度 O(logn) 的解法

输入描述:
一个正整数n

返回值描述:
输出一个正整数。

示例1

输入:4

返回值:3

说明:根据斐波那契数列的定义可知,fib(1)=1,fib(2)=1,fib(3)=fib(3-1)+fib(3-2)=2,fib(4)=fib(4-1)+fib(4-2)=3,所以答案为3

示例2

输入:1

返回值:1

示例3

输入:2

返回值:1

方法一:递归

斐波那契数列, 经典题. 它的递归定义式是 f(n) = f(n-1) + f(n-2) , 因此通过递归来实现.

class Solution {
public:
    int Fibonacci(int n) {
        if(n==0) return 0;
        if(n==1) return 1;
        return Fibonacci(n-1) + Fibonacci(n-2);
    }
};

运行时间:343ms
超过12.03% 用C++提交的代码
占用内存:652KB
超过38.59%用C++提交的代码

上面的递归轨迹我们可以自己心里推导一下, 发现会有许多重复的计算. 比方说计算 f(5) 时根据f(5)=f(4)+f(3) 计算了一遍 f(3) , 后续计算 f(4) 时又根据 f(4)=f(3)+f(2)f(3) 重复计算了一次. 可以画个递归树便于形象地理解.

方法二:动态规划

虽然方法一可以解决此题了,但是如果想让空间继续优化,那就用动态规划,优化掉递归栈空间。 方法二是从上往下递归的然后再从下往上回溯的,最后回溯的时候来合并子树从而求得答案。 那么动态规划不同的是,不用递归的过程,直接从子树求得答案。过程是从下往上

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

继续优化 发现计算 f[5] 的时候只用到了 f[4]和f[3], 没有用到f[2]…f[0],所以保存f[2]…f[0]是浪费了空间。 只需要用3个变量即可。

class Solution {
public:
    int Fibonacci(int n) {
        int a = 1 , b = 1 , c = 1;
        for (int i = 3 ; i <= n ; i ++) {
            c = a + b , a = b , b = c;
        }
        return c;
    }
};

运行时间:3ms
超过42.75% 用C++提交的代码
占用内存:528KB
超过59.68%用C++提交的代码

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

千北@

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值