斐波那契数列

概述:

  斐波那契数列,又称黄金分割数列,指的是如此3个数列:0、1、1、二、③、伍、八、一三、21、34、……在数学上,斐波纳契数列以如下被以递归的措施定义:F(0)=0,F(一)=一,F(n)=F(n-1)+F(n-二)(n≥二,n∈N*)在今世物理、准晶体结构、化学等领域,斐波纳契数列都有直接的应用,为此,美利哥数学会从1玖陆三起出版了以《斐波纳契数列季刊》为名的一份数学杂志,用于专门刊登那地点的商量成果。

 

求解:

求解斐波那契数列的F(n)有三种常用算法:递归算法和非递归算法。试分析两种算法的时日复杂度。

一 递归算法

#!/usr/bin/env python
# -*- coding:utf-8 -*-

def fibonacci(n):
    if n == 0:
        return 0
    elif n <= 2:
        return 1
    else:
        return fibonacci(n-1) + fibonacci(n-2)

fibonacci(100)

光阴复杂度:求解F(n),必须先计算F(n-一)和F(n-2),总计F(n-一)和F(n-二),又必须先总括F(n-三)和F(n-肆)。。。。。。就那样类推,直至必须先总括F(壹)和F(0),然后逆推得到F(n-1)和F(n-2)的结果,从而赢得F(n)要计算诸多双重的值,在时光上导致了极大的荒废,算法的时光复杂度随着N的附加显示指数提升,时间的复杂度为O(2^n),即二的n次方 

2 非递归算法

#!/usr/bin/env python
# -*- coding:utf-8 -*-

def fibonacci(n):
    if n == 0:
        return 0
    elif n <= 2:
        return 1
    else:
        num1 = 1
        num2 = 1
        for i in range(2,n-1):
            num1,num2 = num2,num2 + num1
        return num1 + num2
print(fibonacci(100))

算法复杂度:从n>2开始总括,用F(n-壹)和F(n-二)五个数相加求出结果,那样就制止了汪洋的再度总结,它的成效比递归算法快得多,算法的年华复杂度与n成正比,即算法的小运复杂度为O(n)

 

Python开拓【算法】:斐波那契数列二种时光复杂度,python斐波那契

前言:斐波那契作为3个算法基础知识,大家自然要调整,祝大家学得春风得意~

一. 怎么是斐波那契数?

此处本人借用百度全面上的解释:斐波那契数,亦称作斐波那契数列(意大利共和国语:
Successione di
Fibonacci),又称黄金分割数列、费波那西数列、费波拿契数、费氏数列,指的是这样3个数列:0、壹、一、二、三、5、八、一三、二一、……在数学上,斐波纳契数列以如下被以递归的措施定义:F0=0,F壹=一,Fn=Fn-1+Fn-二(n>=二,n∈N*),用文字来讲,正是斐波那契数列列由
0 和 一起初,之后的斐波那契数列周到就由在此以前的两数相加。特别提出:0不是第三项,而是第零项。

在那一个斐波那契数列中的数字,就被称呼斐波这契数。这些级数与大自然植物的关联极为密切。差不多具有花朵的花瓣数都源于那个级数中的一项数字:凤梨表皮方块形鳞苞产生两组旋向相反的螺线,它们的条数必须是这一个级数中紧邻的多个数字(如左旋捌行,右旋一3行);还有向日葵花盘……直到日前的19九三年,人们才对这几个古老而首要的级数给出真正满足的阐述:此级数中任何相邻的多个数,次第相除,其比率都但是接近0.618034……那些值,它的巅峰就是所谓的”黄金分割数”。

斐波那契数列

概述:

  斐波那契数列,又称黄金分割数列,指的是这么1个数列:0、1、1、二、叁、5、八、一3、2一、3四、……在数学上,斐波纳契数列以如下被以递归的法门定义:F(0)=0,F(一)=一,F(n)=F(n-壹)+F(n-二)(n≥贰,n∈N*)在现世物理、准晶体结构、化学等世界,斐波纳契数列都有平素的施用,为此,美利坚合众国数学会从196三起出版了以《斐波纳契数列季刊》为名的一份数学杂志,用于专门刊登这上头的讨论成果。

 

求解:

求解斐波那契数列的F(n)有二种常用算法:递归算法和非递归算法。试分析三种算法的小时复杂度。

一 递归算法

#!/usr/bin/env python
# -*- coding:utf-8 -*-

def fibonacci(n):
    if n == 0:
        return 0
    elif n <= 2:
        return 1
    else:
        return fibonacci(n-1) + fibonacci(n-2)

fibonacci(100)

时刻复杂度:求解F(n),必须先总计F(n-壹)和F(n-二),总计F(n-一)和F(n-二),又无法不先计算F(n-三)和F(n-肆)。。。。。。就那样推算,直至必须先计算F(1)和F(0),然后逆推获得F(n-一)和F(n-二)的结果,从而获取F(n)要总计诸多再次的值,在时间上产生了异常的大的荒废,算法的时刻复杂度随着N的增大显示指数提升,时间的复杂度为O(二^n),即二的n次方 

二 非递归算法

#!/usr/bin/env python
# -*- coding:utf-8 -*-

def fibonacci(n):
    if n == 0:
        return 0
    elif n <= 2:
        return 1
    else:
        num1 = 1
        num2 = 1
        for i in range(2,n-1):
            num2 = num2 + num1
            num1 = num2 - num1
        return num1 + num2
print(fibonacci(100))

算法复杂度:从n>2起始测度,用F(n-一)和F(n-二)多个数相加求出结果,那样就制止了大气的重复总计,它的成效比递归算法快得多,算法的日子复杂度与n成正比,即算法的光阴复杂度为O(n)

【金沙注册送58】python斐波那契,斐波那契数与二分法的递归与非递归算法及其复杂度分析。 

斐波那契数列 概述:
斐波那契数列,又称黄金分割数列,指的是那样一…

哪些是斐波那契数列(Fibonacci sequence)?

斐波那契数列(Fibonacci
sequence),又称金子分割数列、因数学家列昂纳多·斐波那契(Leonardoda
Fibonacci)以兔子繁殖为例子而引进,故又称为“兔子数列”,指的是如此叁个数列:一、一、二、3、伍、8、13、二一、3四、……在数学上,斐波纳契数列以如下被以递归的章程定义:F(0)=0,F(一)=一,
F(n)=F(n-一)+F(n-二)(n>=②,n∈N*)。

二. 求第N个斐波那契数

求第N个斐波那契数比较轻易能够一向套用公式n = 0,1 时,fib(n) = 壹;n >
=2 时,fib(n) = fib(n-贰) +
fib(n-壹)在盘算时有两种算法:递归和非递归。如下:

 1 //非递归算法
 2 long long fib1(size_t N) {
 3     long long a = 0, b = 1, c = 0;
 4     if (N < 2) {
 5         return N;
 6     }
 7     else {
 8         for (long long i = 2; i <= N; ++i) {
 9             c = a + b;
10             a = b;
11             b = c;
12         }
13     }
14         return c;
15 }
16 int main()
17 {
18     printf("%lld", fib1(10));
19     getchar();
20     return 0;
21 }  //此算法最大的优点是不存在重复计算,故效率比递归算法快的多得多。

 1 //递归算法
 2 long long fib2(size_t N) {
 3     if (N < 2) 
 4         return N;
 5     return fib2(N - 1) + fib2(N - 2);
 6 }
 7 int main()
 8 {
 9     printf("%lld", fib2(10));
10     getchar();
11     return 0;
12 }

递归能够使程序看起来相比简单,但缺点是作用极低,并且大概形成栈溢出,当要求计算的数稍大学一年级些,就须要很短的总计时间,由此必要灵活运用递归。

方式一:递归

F(n)=F(n-1)+F(n-二),利用递归理念,每回计算当前的值时候,即将引用此前的三个值,一步一步的递归,一贯到最起初处,直至F(1)和F(二)。

递归算法程序:

金沙注册送58 1金沙注册送58 2

long long Fib1(long long n)
{
    assert(n >= 0);
    //递归
    return n < 2 ? n : (Fib1(n - 1) + Fib1(n - 2));
}

View Code

递归算法中有恢宏的再次总计,效能低下,当供给计算的数稍大学一年级点,就须求相当长的一个钱打二15个结时间,乃至大概导致栈溢出,但优点是代码轻易,轻巧领会。

递归的吃水*老是递归所需的帮手空间的个数 ,所以空间复杂度是:O(N)。

递归算法时间复杂度为:O(二^(N/2)) <= T(N) <=
O(二^N)。总计进度有个别复杂,需求使用线性代数知识(红衣教主出没~)。

明显,设T(n)为参数为n时的大运复杂度,则T(n)=T(n-一)+T(n-二) 。

那是数学上的二阶常周详差分方程,并且为齐次方程。 特征方程为:x^二-x-一=0
。解得 x=(1±√伍)/贰 。

金沙注册送58 3

 

叁. 二分法查找

方式二:非递归

一.创制贰个数组,每回将前七个数相加后一向赋给后2个数。这样的话,有N个数就创建一个分包N个数的一维数组,所以空间复杂度为O(N);由于只需从头向尾遍历1边,时间复杂度为O(N)。在频仍查询斐波那契数能够先起始化就求出数组,那样查询时间复杂度正是O(一)了。

金沙注册送58 4金沙注册送58 5

long long* Fib2(long long n)
{
    assert(n >= 0);
    //非递归
    long long* F = new long long[n + 1];
    F[0] = 0;
    F[1] = 1;
    for (int i = 2; i <= n; i++)
        F[i] = F[i - 1] + F[i - 2];

    return F;
}

View Code

二.依靠八个变量first和second,每一趟将first和second相加后赋给third,再将second赋给first,third赋给second,时间复杂度为O(N),空间复杂度为O(一)。只用于求单个斐波那契数,标题中一般不这么写,查询复杂度为O(N)。

金沙注册送58 6金沙注册送58 7

long long Fib3(long long n)
{
    assert(n >= 0);

    long long first = 0;
    long long second = 1;
        if(n < 2) return n;

    long long third;
    for(int i = 2; i <= n; i++)
    {
        third = first + second;
        first = second;
        second = third;
    }
    return third;
}

View Code

计量进程:一般情况下,对步进循环语句只需思虑循环体中语句的推行次数,忽略该语句中山大学幅度加一、终值判断、调节转移等成份,当有多少个循环语句时,算法的时刻复杂度是由嵌套层数最多的循环语句中最内层语句的频度f(n)决定的。这里T(n)
= 三 * (n – 2) = O(N)。

三.一 二分查找的非递归算法

 1 template<typename T>  
 2 T* BinarySearch(T* array,int number,const T& data)  //data要查找的数,number查找范围长度,array要查找的数组
 3 {  
 4        assert(number>=0);  
 5        int left = 0;  
 6        int right = number-1;  
 7        while (right >= left)  
 8        {  
 9               int mid = (left&right) + ((left^right)>>1);  
10               if (array[mid] > data)  
11               {  
12                      right = mid - 1;  
13               }  
14               else if (array[mid] < data)  
15               {  
16                      left = mid + 1;  
17               }  
18               else  
19               {  
20                      return (array + mid);  
21               }  
22        }  
23        return NULL;  
24 }  

主意三:火速矩阵幂

金沙注册送58,先精晓一下,什么是矩阵快捷幂。

斐波这契数列的微型计算机算法是行使矩阵,二阶叁阶都得以,这里比方二阶。

金沙注册送58 8

咱俩应用高效矩阵幂算法,能够在O(logN)时间内获得答案,那种艺术还有3个优点,在总结相当大n时显得十三分有效。

那边给出急速矩阵幂的沙盘,可借鉴:

金沙注册送58 9金沙注册送58 10

const int N = 2;

struct Matrix {
    int mat[N][N];
    Matrix() {}
    Matrix operator * (const Matrix& b) const {
        Matrix result;
        memset(result.mat, 0, sizeof(result.mat));
        for (int i = 0; i < N; ++i) {
            for (int j = 0; j < N; ++j) {
                for (int k = 0; k < N; ++k) {
                    result.mat[i][j] = (result.mat[i][j] + this->mat[i][k] * b.mat[k][j]) ;
                }
            }
        }
        return result;
    }
};

Matrix MatPow(Matrix base, int n)
{
    Matrix result;
    memset(result.mat, 0, sizeof(result.mat));
    for (int i = 0; i < N; ++i) {
        result.mat[i][i] = 1;
    }

    while (n > 0)
    {
        if(n & 1) result = result * base;
        base = base * base;
        n >>= 1;
    }
    return result;
}

View Code

 

三.二 二分查找递归算法

 1 template<typename T>  
 2 T* BinarySearch(T* left,T* right,const T& data)  
 3 {  
 4        assert(left);  
 5        assert(right);  
 6        if (right >=left)  
 7        {  
 8               T* mid =left+(right-left)/2;  
 9               if (*mid == data)  
10                      return mid;  
11               else  
12                      return *mid > data ? BinarySearch(left, mid - 1, data) : BinarySearch(mid + 1, right, data);  
13        }  
14        else  
15        {  
16               return NULL;  
17        }  
18 }  

算法第壹回演习赛指引

首先题就1个简便的斐波那契数列呀,为啥泥萌都开2维数组,明明只要二个5一的数组就够了。

其次题开一个数组就好,为啥被误导成开四个数组呢?

其三题也是斐波那契数列,百度时而矩阵求斐波那契,一分钟AC,不过如故建议熟谙矩阵急速幂的求解。

第四题相对不是如何DP,扫描三次O(N)化解就ok。

第5题?HINT里有写使用优先队列了,不懂的尽早学习一下STL吧!

第6题?听他们讲你推出了公式直接求出答案?想1想结束时并不是各类机器人能量都用光就通晓了,换个办法吧,比方二分~

 小编要去做演练赛!

大家加油~

 

作者: AlvinZH

出处: http://www.cnblogs.com/AlvinZH/

本文版权归小编AlvinZH和微博全部,接待转发和商用,但未经小编同意必须保留此段证明,且在作品页面显明地点给出最初的文章连接,不然保留追究法律义务的权利。

四. 岁月复杂度与空间复杂度

时间复杂度:一般情况下,算法中基本操作重复施行的次数是主题材料规模n的某部函数f(n),进而分析f(n)随n的变动景况并鲜明T(n)的多寡级。这里用”O”来代表数量级,给出算法的日子复杂度。

      T(n)=O(f(n));                 

 
它象征随着难题规模的n的增大,算法的实行时间的拉长率和f(n)的增加率一样,那称作算法的渐进时间复杂度,简称时间复杂度。而笔者辈一般研讨的是最坏时间复杂度,那样做的原故是:最坏处境下的时日复杂度是算法在其它输入实例上运转时刻的上界,分析最坏的景观以估算算法指向时间的1个上界。

岁月复杂度的分析方法:

(一)时间复杂度就是函数中基本操作所推行的次数;

(二)一般默许的是最坏时间复杂度,即分析最坏情形下所能实施的次数;

(3)忽略掉常数项;

(肆)关切运行时刻的巩固趋势,关怀函数式中抓好最快的表明式,忽略周详;

(伍)计算时间复杂度是猜度随着n的增进函数试行次数的拉长势头;

(6)递归算法的年华复杂度为:递归总次数 *
每一回递归中基本操作所施行的次数;

   
常用的时日复杂度有以下多样,算法时间复杂度依次增加:O(一)常数型、O(log二 n)对数型、O(n)线性型、O(nlog2n)贰维型、O(n^二)平方型、O(n^3)立方型、O(2^n)指数型。

空间复杂度:

 
算法的半空中复杂度并不是计量实际占用的空中,而是总括整个算法的救助空间单元的个数,与难题的框框未有关系。算法的长空复杂度S(n)定义为该算法所开销空间的数目级。

  S(n)=O(f(n))
 若算法施行时所急需的扶植空间相对于输入数据量n来讲是贰个常数,则称那么些算法的推来推去空间为O(一); 

  递归算法的长空复杂度:递归深度N*老是递归所要的帮扶空间,
即便每趟递归所需的扶助空间是常数,则递归的上空复杂度是 O(N)。

五. 斐波那契数的时辰复杂度与上空复杂度分析

5.1 非递归算法时间复杂度分析

 使用非递归算法求到第n个斐波那契数,是从第一个数开首,将前八个数相加求求后1个数,再将后七个数赋值给前贰个数,再总结前八个数相加的结果。依次类推直到第n个数,用n-二个数和n-一个数相加求出结果,那样的裨益是,大家只计算了n-三次就求出了结果,即时间复杂度为O(n);我们以代码中测试数十为例详解求第玖个数的经过。当N=十时,进入函数首先判别,然后走上边的分段起始妄图

金沙注册送58 11

总括了N-三回,得出了结果所以时间复杂度是O(N)。

非递归算法空间复杂度分析
此函数内部最多时一共开辟了a, b, c, i四个变量空间复杂度是常数,即为O(1)。 

5.贰 递归算法时间复杂度分析

在递归算法中,求解fib2(n),把它推到求解fib贰(n-一)和fib2(n-二)。也正是说,为总计fib二(n),必须先总计

fib二(n-一)和fib二(n-二),而计量fib2(n-1)和fib二(n-二),时坚守表明式及总括法则,需先总计又必须先总括fib二(n-一),而fib二(n-一)由fib二(n-贰)和fib2(n-三)总计得来,而那在那之中的和fib贰(n-二)由fib贰(n-三)和fib二(n-4)总结得来……依次类推,表面上看不出有啥复杂度,但是仔细分析可见,每1个划算fib贰(n)的道岔都会衍生出计算直至(壹)和fib(0),也正是说每一个分支都要和煦总结数本身到一的斐波那契数列,那样就充实了比相当大且冗杂的运算量,依旧以十为例详细总括表明

金沙注册送58 12

图中数字代表第N个斐波那契数,图中没有任何将计算步骤画出来,然而已经足足表达难点,它的每一步总计都被分成总结前四个斐波那契数,就那样推算。那么这就变成了一颗二叉树,就算不是满贰叉树,不过大家分析的是最坏时间复杂度,而且要是估量出来递归次数随N增加的来头就能够,故能够接近将它看作满贰叉树,当中的节点数就是计量的次数,也正是复杂度,由公式:节点数=二^h-1(h为树的中度)可得O(贰^n)。

递归的大运复杂度是:
 递归次数*老是递归中试行基本操作的次数,所以时间复杂度是: O(二^N)

递归算法空间复杂度分析:

递归最深的那1回所开支的空中可以容纳它具有递归进程。递归产生的栈侦是要绝迹的,所以空间也就释放了,要赶回上一层栈侦继续总计+号后边的数,所以它所须求的半空中不是直接增加起来的,之后爆发的栈侦空间都低于递归最深的那贰遍所开销的空间。

递归的深度*历次递归所需的帮带空间的个数 ,所以空间复杂度是:O(N)

陆. 求二分法的时间复杂度和空中复杂度

 6.一  非递归算法分析

金沙注册送58 13

分析:

倘诺最坏情状下,循环X次之后找到,则:二^x=n;
x=logn(算法中壹旦没写,log私下认可底数为二)

巡回的主干次数是log二 N,所以: 时间复杂度是O(logN);

出于接济空间是常数等第的之所以:空间复杂度是O(一);

陆.二 递归算法复杂度分析

金沙注册送58 14

假如最坏情形下,循环X次之后找到,则:贰^x=n;
x=logn(算法中若是没写,log暗中同意底数为二)

递归的次数和纵深都以log贰 N,每一回所要求的援助空间都是常数等级的:

岁月复杂度:O(log二 N);

空间复杂度:O(log贰N )。

柒.  扩充—–不用循环法和递归法求一+二+三+…+N(思索壹种复杂度为O(一)的解法)

 1 class Temp
 2 {
 3 public:
 4     Temp(){
 5         ++N;
 6         Sum += N;
 7     }
 8     static void Reset(){
 9         N = 0;
10         Sum = 0;
11     }
12     static int GetSum(){
13         return Sum;
14     }
15 private:
16     static int N;
17     static int Sum;
18 };
19 int Temp::N = 0;
20 int Temp::Sum = 0;
21 int solution_Sum(int n){
22     Temp::Reset();
23     Temp *a = new Temp[n];
24     delete[]a;
25     a = 0;
26     return Temp::GetSum();
27 }
28 int main(){
29     cout << solution_Sum(100) << endl;
30     getchar();
31     return 0;
32 
33 }

相关文章

网站地图xml地图