zoukankan      html  css  js  c++  java
  • 剑指offer-第二章算法之斐波拉契数列(青蛙跳台阶)

    递归与循环

    递归:在一个函数的内部调用这个函数。

    本质:把一个问题分解为两个,或者多个小问题(多个小问题相互重叠的部分,会存在重复的计算)

    优点:简洁,易于实现。

    缺点:时间和空间消耗严重,如果递归调用的层级太多,就会超出栈容量。

    循环:通过设置计算的初始值及终止条件,在一个范围内重复运算。

    斐波拉契数列

    题目一:写一个函数,输入n,求斐波拉契(Fibonacci)数列的第n项,定义如下:

    第一种解法:用递归的算法:

    long long Fabonacci(unsigned int n)
    {
    	if(n<=0)
    		return 0;
    	if(n==1)
    		return 1;
    	return Fabonacci(n-1)+Fabonacci(n-2);
    }
    

     当n=10的时候的调用图如下:

    从上图我们可以看到递归的时候,有很多数都被重复计算了,对性能带来极其负面的影响,改算法的时间复杂度为n的指数次方。

    第二种解法:用循环(时间复杂度为O(n))

    #include <iostream>
    using namespace std;
    long long Fabonacci(unsigned int n)
    {
        int arrary[2]={0,1};
        long long FabN;
    
        if(n<2)
            FabN=arrary[n];
        long long FabOne=1;
        long long FabTwo=0;
        for(unsigned int i=2;i<=n;++i)
        {
            FabN=FabOne+FabTwo;
            FabTwo=FabOne;
            FabOne=FabN;
        }
        return FabN;
    }
    void main()
    {
     long long n=Fabonacci(15);
     cout<<n<<endl;
    
    }

    java代码:

    public class Fabonacci {
          //斐波拉契数列的非递归的实现,用循环。时间复杂度为O(n)
        public int fabonacci(int n){
            int[] a={0,1};
            if(n<2)
                return a[n];
            int FabOne=0;
            int FabTwo=1;
            int FabN=0;
            for(int i=2;i<=n;i++){
                FabN=FabOne+FabTwo;
                FabOne=FabTwo;
                FabTwo=FabN;
            }
            return FabN;
        }
        //斐波拉契数列的递归写法
        public long fabonacci1(long n){
            long fabN=0;
            if(n<=0)
              fabN=0;
            else if(n==1)
              fabN=1;
            else
                fabN=fabonacci1(n-1)+fabonacci1(n-2);
            return fabN;
        }
        public static void main(String[] args){
            Fabonacci fab=new Fabonacci();
            int f=fab.fabonacci(5);
            long f1=fab.fabonacci1(5);
            System.out.println(f+" "+f1);
        }
    }


    题目二:一只青蛙一次可以跳上一级台阶,也可以跳上2级台阶,求该青蛙跳上n级台阶的共有多少种跳法。

    思路:当只有一级台阶的时候,青蛙的跳法也只有一种。当有两级台阶的时候,青蛙的跳法有两种(一是:一下跳两级台阶,二是:一级一级的跳)。当有n级台阶的时候,青蛙在第一次起跳的时候只跳了一级台阶,则还剩下n-1级台阶的跳法,如果在第一次起跳的时候跳了两级台阶,则还剩下n-2级台阶的跳法。整个题目正好是一个斐波拉契数列。公式如下:

     题目三:矩阵的覆盖,用八个2*1的小矩阵去覆盖一个2*8的大矩阵。如下图所示:

    第一个小矩阵可以有两种覆盖方法横着,那么此时,必须由第二个小矩阵也横着,剩下2*6的大矩阵;竖着,那么还剩下2*7的大矩阵需要覆盖。因此可得:f(8)=f(6)+f(7).

    公式同上第二题。

  • 相关阅读:
    eclipse插件egit安装使用
    github 项目版本控制
    div box container随主体内容自动扩展适应的实现
    持续构建与每日集成
    Xshell连接Linux下Oracle无法回退的解决办法
    Java Data JPA +hibernate 保存或者是查询遇到的坑
    C#控件DropDownList下拉列表默认打开
    window.open居中显示
    CSV文件转JSON
    Vue自定义事件,$on(eventName) 监听事件,$emit(eventName) 触发事件
  • 原文地址:https://www.cnblogs.com/hupp/p/4519198.html
Copyright © 2011-2022 走看看