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).

    公式同上第二题。

  • 相关阅读:
    English 2
    速算24点
    心理学1
    从微服务到函数式编程
    034 01 Android 零基础入门 01 Java基础语法 04 Java流程控制之选择结构 01 流程控制概述
    033 01 Android 零基础入门 01 Java基础语法 03 Java运算符 13 运算符和表达式知识点总结
    032 01 Android 零基础入门 01 Java基础语法 03 Java运算符 12 运算符和if-else条件语句的综合案例——闰年问题
    031 01 Android 零基础入门 01 Java基础语法 03 Java运算符 11 运算符的优先级
    030 01 Android 零基础入门 01 Java基础语法 03 Java运算符 10 条件运算符
    029 01 Android 零基础入门 01 Java基础语法 03 Java运算符 09 逻辑“非”运算符
  • 原文地址:https://www.cnblogs.com/hupp/p/4519198.html
Copyright © 2011-2022 走看看