JZ7--JZ10斐波那契数列及其变体

JZ7斐波那契数列

题目描述
大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0,第1项是1)。n<=39

示例1
输入
4
返回值
3

方法一:递归(从上向下计算)
题目分析,斐波那契数列公式为:f[n] = f[n-1] + f[n-2], 初始值f[0]=0, f[1]=1,目标求f[n]
看到公式很亲切,代码秒秒钟写完。

int Fibonacci(int n) {
    
    
    if (n==0 || n==1) return n;
    return Fibonacci(n-1) + Fibonacci(n-2);
}

时间复杂度:O(2^n)
空间复杂度:递归栈的空间
优点:代码简单好写,缺点:慢,会超时(效率低)

效率低的原因:
在这里插入图片描述
方法二:循环(从下向上计算)------------推荐
为了优化方法一(递归)中的重复计算,解决办法是按上面树状图从下向上循环)计算

class Solution {
    
    
public:
    int Fibonacci(int n) {
    
    
        if(n<=0) return 0;
        if(n==1) return 1;
        int ret;
        int FibN=0;
        int FibMinusOne=1;//Minus:减
        int FibMinusTwo=0;
        for(int i=2;i<=n;i++){
    
    
            FibN=FibMinusOne+FibMinusTwo;
            FibMinusTwo=FibMinusOne;
            FibMinusOne=FibN;
        }
        return FibN;
 
    }
};

时间复杂度:O(n)
空间复杂度:O(1)

JZ8跳台阶

题目描述
一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。

示例1
输入
1
返回值
1
示例2
输入
4
返回值
5

题解:
只有1级台阶:f(1)=1;
只有2级台阶:f(2)=2;----------一种跳两次,一次跳1级;一种跳一次,一次跳2级
有n级台阶 :
在这里插入图片描述
这就得到了熟悉的公式:在这里插入图片描述

递归

class Solution {
    
    
public:
    int jumpFloor(int number) {
    
    
        if(number==1) return 1;
        if(number==2) return 2;
        return jumpFloor(number-1)+jumpFloor(number-2);
    }
};

时间复杂度:O(2^n)
空间复杂度:递归栈的空间
循环-----------推荐(优化)

class Solution {
    
    
public:
    int jumpFloor(int number) {
    
    
        if(number==1) return 1;
        if(number==2) return 2;
        int floorN=0, floorMinusOne=2,floorMinusTwo=1;//注意floorMinusOne,floorMinusTwo的赋值,别赋反了;
        for(int i=3;i<=number;i++){
    
    
            floorN=floorMinusOne+floorMinusTwo;
            floorMinusTwo=floorMinusOne;
            floorMinusOne=floorN;
        }
        return floorN;
    }
};

时间复杂度:O(n)
空间复杂度:O(1)

JZ9变态跳台阶

题目描述
一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。

示例1
输入
3
返回值
4

题解:
f[i] 表示 当前跳道第 i 个台阶的方法数。那么f[n]就是所求答案。
跳上n级,有如下情况:
第一步跳1级,还剩n-1级,此时跳法数等于后面n-1级台阶跳法数:f(n-1)
第一步跳2级,还剩n-2级,此时跳法数等于后面n-2级台阶跳法数:f(n-2)
。。。。。。
第一步跳n-1级,还剩1级,此时跳法数等于后面1级台阶跳法数:f(n-(n-1))=f(1)=1
第一步跳n级,还剩0级,此时跳法数等于f(n-n)=f(0)=1

即:f[n] = f[n-1] + f[n-2] + … + f[0], 初始条件f[0] = f[1] = 1

方法一:暴力方法
根据公式,我们就可以先求f[2],然后f[3]…f[n-1], 最后f[n]

int jumpFloorII(int n) {
    
    
    if (n==0 || n==1) return 1;
    vector<int> f(n+1, 0);// f[i]的初始值为0;
    f[0] = f[1] = 1;
    for (int i=2; i<=n; ++i) {
    
    
        for (int j=0; j<i; ++j) {
    
    
            f[i] += f[j];// f[i]的初始值为0;
        }
    }
    return f[n];
}

时间复杂度:O(n^2)
空间复杂度:O(n),创建了一个 vector<int> f(n+1, 0);
方法二:递推(数学化简)--------推荐

易知 f(n)=f(n-1)+f(n-2)+……f(1)+f(0)
f(n-1)=f(n-2)+……f(1)+f(0)
两式相减得f(n)=2f(n-1)

以n=4为例:
在这里插入图片描述
递归实现(从上向下)

class Solution {
    
    
public:
    int jumpFloorII(int number) {
    
    
        if(number==0||number==1) return 1;
        return 2*jumpFloorII(number-1);
    }
};

时间复杂度:O(n)
空间复杂度:递归栈的空间

循环实现(从下向上)---------推荐

class Solution {
    
    
public:
    int jumpFloorII(int number) {
    
    
        int n=1;
        for(int i=1;i<number;i++){
    
    
            n=2*n;
        }
        return n;
 
    }
};

时间复杂度:O(n)
空间复杂度:O(1)

JZ10矩形覆盖

题目描述
我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?

比如n=3时,2*3的矩形块有3种覆盖方法:
在这里插入图片描述

示例1
输入
4
返回值
5

题解参考这里
即,用f [n]表示2*n大矩阵 的方法数。
显然:
n=1,f(1)=1;
n=2,f(2)=2;
对于2*n大矩阵,覆盖它的最右面的2*1小矩阵,要么是竖着的,要么是横着的;
最右边是竖着的需要1个小矩阵(去除这一个竖着的,相当于剩下个2*n-1大矩阵,此时覆盖方法是f(n-1)),
横着的需要2个(去除这两个横着的,相当于剩下个2*n-2大矩阵,此时覆盖方法是f(n-2))。
可以得出:
f[n] = f[n-1] + f[n-2],初始条件f[1] = 1, f[2] =2
是斐波那契数列,则用从下向上的循环方式实现它:

class Solution {
    
    
public:
    int rectCover(int number) {
    
    
        if(number<=2) return number;
        int f1=1,f2=2;
        int fn;
        for(int i=3;i<=number;i++){
    
    
            fn=f1+f2;
            f1=f2;
            f2=fn;
        }
        return fn;
 
    }
};

知识点

1.斐波那契数列的题都是从上向下分析,直观上用递归实现,但实际上都会考虑效率问题,采用for循环的形式按从下向上写代码。

猜你喜欢

转载自blog.csdn.net/qq_42647047/article/details/110110873