算法题目

查找斐波纳契数列中第 N 个数。

所谓的斐波纳契数列是指:

* 前2个数是 0 和 1 。

* 第 i 个数是第 i-1 个数和第i-2 个数的和。

斐波纳契数列的前10个数字是:

0, 1, 1, 2, 3, 5, 8, 13, 21, 34 …

分析

斐波那契数列满足公式f(n) = f(n-1) + f(n-2),n > 0。这里我们的第一想法是使用递归,可是直接翻译公式出来的递归调用是这样的:

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

可是这个函数的事件复杂度恰好是最糟糕的指数级。怎么来证明它是指数级呢?

你可以先用一些测试数来测试一下这个方法:

当n = 40时,大概就需要0.5秒才能计算出来;

当n 为50时,需要等很久才能计算出实际的值。

下面来推导它的时间复杂度。

对于斐波那契数,有定理 :当n >= 0时,Fn < (5/3)n

首先使用归纳法来证明。对于基准情形,F1 = 0 < 5/3,F2 = 1 < 5/3。

然后假设i = 1,2,3,…,n 成立;这就是归纳假设。那么我们只需要证明出Fn+1 < (5/3)n+1 即可。

根据公式我们可以得出Fn+1 = Fn + Fn-1

推到过程如下:

Fn+1 < (5/3)n + (5/3)n-1

Fn+1 < (3/5)(5/3)n+1 + (3/5)2(5/3)n+1

Fn+1 < (24/25)(5/3)n+1 < (5/3)n+1

得证 Fn+1 < (5/3)n+1

同样的证明过程,可以证明出当n > 4时, Fn > (3/2)n

而T(n) = T(n-1) + T(n-2) + 3。

T(n) >= fib(n) >= (3/2)n

因此这个函数的运行时间是以指数的速度增长。

可能有点不同的是,有的斐波那契数列是从1,1,2,3,…. 开始,所以有些微的差别。

这只是对级数做了一次平移。我们可以找一些方便证明的情况来证明。

更优解法

其实上面的递归违反了递归的合成效益法则,才导致了运行时间的指数级增长。

递归的四条基本准则:

1、基准情形。必须有总有某些基准情形,它无须递归就能解出。

2、不断推进。对于那些需要递归求解的情形,每一次递归调用都必须要使求解状况朝接近基准情形的方向推进。

3、设计法则。假设所有的递归调用都能运行。

4、合成效益法则。在求解一个问题的同一示例时,切勿在不同的递归调用中做重复性的工作。

我们可以利用一个简单的for 循环来求解第N个斐波那契数。

int fibonacci(int n) {
if (n == 1) {
return 0;
} if (n == 2) {
return 1;
} int a = 0;
int b = 1;
int c = 0;
for (int i = 3; i < n + 1; i++) {
c = a + b;
a = b;
b = c;
}
return c;
}

使用两个变量分别保存f(n-1) 和f (n-2),然后从基准情况开始往第 n 个数推进。

改进后的函数时间复杂度是O(n),运行时间大概是 (3n - 1)大大减少了运行时间。

算法之路(三)----查找斐波纳契数列中第 N 个数的更多相关文章

  1. Java算法求最大最小值,冒泡排序,斐波纳契数列一些经典算法<不断更新中>

    清明在家,无聊,把一些经典的算法总结了一下. 一.求最大,最小值 Scanner input=new Scanner(System.in); int[] a={21,31,4,2,766,345,2, ...

  2. lintcode:Fibonacci 斐波纳契数列

    题目: 斐波纳契数列 查找斐波纳契数列中第 N 个数. 所谓的斐波纳契数列是指: 前2个数是 0 和 1 . 第 i 个数是第 i-1 个数和第i-2 个数的和. 斐波纳契数列的前10个数字是: 0, ...

  3. LintCode 斐波纳契数列

    查找斐波纳契数列中第 N 个数. 所谓的斐波纳契数列是指: 前2个数是 0 和 1 . 第 i 个数是第 i-1 个数和第i-2 个数的和. 斐波纳契数列的前10个数字是: 0, 1, 1, 2, 3 ...

  4. Java算法求最大最小值,倒序,冒泡排序,斐波纳契数列,日历一些经典算法

    一,求最大,最小值 int[] a={21,31,4,2,766,345,2,34}; //这里防止数组中有负数,所以初始化的时候给的数组中的第一个数. int max=a[0]; int min=a ...

  5. java斐波纳契数列

    //斐波纳契数列,又称黄金分割数列,指的是这样一个数列:1.1.2.3.5.8.13.21.-- 这个数列从第三项开始,每一项都等于前两项之和. public class DiGui { public ...

  6. HDU 4639 Hehe(字符串处理,斐波纳契数列,找规律)

    题目 //每次for循环的时候总是会忘记最后一段,真是白痴.... //连续的he的个数 种数 //0 1 //1 1 //2 2 //3 3 //4 5 //5 8 //…… …… //斐波纳契数列 ...

  7. 用PHP迭代器来实现一个斐波纳契数列(转)

    斐波纳契数列通常做法是用递归实现,当然还有其它的方法.这里现学现卖,用PHP的迭代器来实现一个斐波纳契数列,几乎没有什么难度,只是把类里的next()方法重写了一次.注释已经写到代码中,也是相当好理解 ...

  8. 10、end关键字和Fibonacci series: 斐波纳契数列

    # Fibonacci series: 斐波纳契数列 # 两个元素的总和确定了下一个数 a, b = 0, 1 #复合赋值表达式,a,b同时赋值0和1 while b < 10: print(b ...

  9. HDU 5914 Triangle 斐波纳契数列 && 二进制切金条

    HDU5914 题目链接 题意:有n根长度从1到n的木棒,问最少拿走多少根,使得剩下的木棒无论怎样都不能构成三角形. 题解:斐波纳契数列,a+b=c恰好不能构成三角形,暴力就好,推一下也可以. #in ...

随机推荐

  1. APP的宣传方式有哪些

    APP应用已经成为了互联网不可缺少的话题,事实上,开发一款移动APP的成本不是很高,但是怎样以最低的成本得到最大的推广效果,这是企业和开发者都很关心的一个问题.下面,我们来探讨一下这个问题. 1.一款 ...

  2. [C#]Google Chrome 书签导出并生成 MHTML 文件

    目的 因为某些原因需要将存放在 Google Chrome 内的书签导出到本地,所幸 Google Chrome 提供了导出书签的功能. 分析 首先在 Google Chrome 浏览器当中输入 ch ...

  3. [LeetCode] Diameter of Binary Tree 二叉树的直径

    Given a binary tree, you need to compute the length of the diameter of the tree. The diameter of a b ...

  4. Python中time模块详解

    Python中time模块详解 在平常的代码中,我们常常需要与时间打交道.在Python中,与时间处理有关的模块就包括:time,datetime以及calendar.这篇文章,主要讲解time模块. ...

  5. [HEOI2016]排序

    题目描述 在2016年,佳媛姐姐喜欢上了数字序列.因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题,需要你来帮助他.这个难题是这样子 的:给出一个1到n的全排列,现在对这个全排列序列进 ...

  6. [POJ]1279: Art Gallery

    题目大意:有一个N边形展馆,问展馆内有多少地方可以看到所有墙壁.(N<=1500) 思路:模板题,半平面交求出多边形的核后计算核的面积. #include<cstdio> #incl ...

  7. poj 2888 Magic Bracelet(Polya+矩阵快速幂)

    Magic Bracelet Time Limit: 2000MS   Memory Limit: 131072K Total Submissions: 4990   Accepted: 1610 D ...

  8. NVisionXR for ARCore内测版开放申请

    NVisionXR for ARCore引擎能够帮助开发者快速开发原生ARCore应用,只要你懂基本的Android开发,直接使用Android Studio,即可实现动画模型渲染.粒子特效.音视频播 ...

  9. 树莓派3B(2)- 配置多个wifi,自动寻找可用网络

    一.背景 在上篇<Raspberry Pi 3B 安装系统并联网>中,树莓派使用wifi连接,但是把树莓派带到公司,树莓派就连不了公司的wifi,要是支持连接多个wifi就好了,在此整理分 ...

  10. asp.net用户控件引用

    <%@ Register Src="~/_module/IndexChannelHead.ascx" TagName="tn" TagPrefix=&qu ...