剑指Offer面试题9(java版)斐波那契数列

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

1、效率很低效的解法,挑剔的面试官不会喜欢

很多C语言的教科书在讲述递归函数的时候,都户拿Fibonacci作为例子,因此很多的应聘者对这道题的递归解法都很熟悉。

下面是实现代码

我们教科书上反复用这个问题来讲解递归的函数,并不能说明递归的解法最适合这道题目。面试官会提示我们上述递归的解法有很严重的效率问题要求我们分析原因。

我们以求解f(10)为例来分析递归的求解过程。想求得f(10),需要先求出f(9)和f(8).同样求f(9),需要先求得f(8)和f(7)。我们用树来构造这种依赖关系。如图所示:

我们不难发现在这颗树中有很多的节点是重复的,而且重复的节点数会随着n的增大而急剧增加,这意味着计算量会随着n的增大而急剧增大。事实上,用递归的方法计算的时间复杂度是以n的指数的方式递增的。读者不妨求Fibonacci的第100项试试,感受一下这样的递归会慢到什么程度。

2、面试官期待的适用解法:

其实改进的方法比并不复杂。上述的递归代码之所以慢是因为重复的计算太多,我们只要想避免重复计算就型了。比如我们可以把已经得到的数列中间项保存起来,如果下次需要计算的时候我们先查找一下,如果前面已经计算过就不用重复计算了。

更简单的方法是从下往上计算,首先计算f(0)和f(1)算出f(2),再根据f(1)和f(2)算出f(3)……依次类推就可以算出第n项了。很容易理解,这种思路的时间复杂度为O(n)。实现代码如下:

/**
 * 写一个函数,输入n,求斐波那契(Fibonacci)数列的第n项。
 */
package swordForOffer;

/**
 * @author JInShuangQi
 *
 * 2015年7月29日
 */
public class E09Fibonacci {
	public long fibonacci(int n){
		long result =0;
		long preOne = 1;
		long preTwo = 0;
		if( n == 0){
			return preTwo;
		}
		if(n == 1){
			return preOne;
		}
		for(int i = 2;i<= n ;i++){
			result = preOne+preTwo;
			preTwo = preOne;
			preOne = result;
		}
		return result;
	}
	public static void main(String[] args){
		E09Fibonacci fabonacci = new E09Fibonacci();
		System.out.println(fabonacci.fibonacci(10));
	}
}

3、时间复杂度O(logn)但不够使用的解法)

通常面试到这里就差不多了,尽管我们还有比这更快的O(logn)解法,由于这种算法需要用到一个很生僻的数学公式,因此很少有面试官会要求我们掌握。不过以防万一,我们还是介绍一下这种算法。

我们先来聊i额一个数学公示:

解法比较:

用不同的方法求斐波那契数列的时间效率大不相同。第一种基于递归的解法虽然直观但时间效率太低,实际软件开发中不会使用这种方法,也不可能得到面试官的青睐。第二种方法把递归的算法用循环来实现,极大的提高了时间效率。第三种方法把求斐波那契数列转换成求矩阵的乘方,是一种很有创意的算法。虽然我们可以哟个O(logn)求的矩阵的n次方,但由于隐含的时间常熟较大,很少会有软件采用这种算法,另外,实现这种算法的代码也交复杂,不太适用于面试。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-11-13 06:41:19

剑指Offer面试题9(java版)斐波那契数列的相关文章

剑指offer面试题14(Java版):调整数组顺序使奇数位于偶数的前面

题目:输入一个整数数组.实现一个函数来调整该数组中数字的顺序.使得全部奇数位于数组的前半部分.全部偶数位于数组的后半部分. 1.基本实现: 假设不考虑时间复杂度,最简单的思路应该是从头扫描这个数组,每碰到一个偶数时,拿出这个数字,并把位于这个数字后面的全部的数字往前面挪动一位. 挪完之后在数组的末尾有一个空位.这时把该偶数放入这个空位. 因为没碰到一个偶数就须要移动O(n)个数字.因此总的时间复杂度是O(n2).可是,这样的方法不能让面试官惬意.只是假设我们在听到题目之后立就可以以说出这个解法,

java输出斐波那契数列

题目要求:编写程序在控制台输出斐波那契数列前20项,每输出5个数换行 斐波那契数列(Fibonacci sequence),又称黄金分割数列.因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为"兔子数列",指的是这样一个数列:1.1.2.3.5.8.13.21.34.--在数学上,斐波纳契数列以如下被以递归的方法定义:F(0)=0,F(1)=1, F(n)=F(n-1)+F(n-2)(n>=2,n∈N*) //Java编程:三种

【Java】斐波那契数列(Fibonacci Sequence、兔子数列)的3种计算方法(递归实现、递归值缓存实现、循环实现)

斐波那契数列:0.1.1.2.3.5.8.13………… 他的规律是,第一项是0,第二项是1,第三项开始(含第三项)等于前两项之和. > 递归实现 看到这个规则,第一个想起当然是递归算法去实现了,于是写了以下一段: public class RecursionForFibonacciSequence { public static void main(String[] args) { System.out.println(recursion(10)); } public static double

Java实现斐波那契数列Fibonacci

import java.util.Scanner; public class Fibonacci { public static void main(String[] args) { // TODO Auto-generated method stub Scanner in=new Scanner(System.in); System.out.println("斐波那契数列的个数是:"); int total=in.nextInt(); System.out.println("

《剑指Offer》——Singleton(Java版)

1.单例模式的定义 单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例. 2.单例模式的特点 单例类只能有一个实例. 单例类必须自己创建自己的唯一实例. 单例类必须给所有其他对象提供这一实例. 3.单例模式的Java代码 单例模式分为懒汉式(需要才去创建对象)和饿汉式(创建类的实例时就去创建对象). 4.饿汉式 在静态代码块实例对象 //在静态代码块实例对象 public class Singleton { private static Singleton singleton

JAVA实现--斐波那契数列

斐波那契数列是我在初中的数学课接触到的,当时唯一对这个感兴趣的是他的名字,因为一直在想是谁起了一个这么别扭的名字-后来无知的我才发现原来是这么一回事: 斐波那契数列:是1202年莱昂纳多·斐波那契提出的,当时只是为了解决一个兔子繁殖的问题,后来再世人的研究与拓展,发现他有非常广泛的应用.下面我们用程序来实现如何计算斐波那契数列: 0,1,1,2,3,5,8,13,21,34-- 上面这个数列有一个递推式和一个初始条件: F[n]=F[n-1]+F[n-2] (n>1) F[0]=0, F[1]=

java实现斐波那契数列和约瑟夫环

斐波那契数列的递归实现: public int fn(int n) { if (n == 1 || n == 2) return 1; return fn(n-1)+fn(n-2); } 非递归写法: public int fn(int n) { int a =1; int b = 1; int tmp; if (n == 1 || n == 2) return 1; for (int i = 2; i < n; i++) { tmp = a +b; a = b; b = tmp; } retu

斐波那契数列【java实现】

java 实现斐波那契数列 以下是Java代码实现(递归与递推两种方式): import java.util.Scanner; /** * Fibonacci * * @author tongqian.zhang */ public class Fibonacci { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.println("Please input

剑指Offer面试题11(Java版):数值的整数次方

题目:实现函数double Power(double base,int exponent),求base的exponent次方.不得使用库函数,同时不需要考虑大数问题 1.自以为很简单的解法: 由于不需要考虑大数问题,这道题看起来很简单,可能不少应聘者在看到题目30秒后就能写出如下的代码: public double powerWithExponent(double base,int exponent){ double result = 1.0; for(int i = 1;i<= exponen

剑指offer编程题Java实现——面试题9斐波那契数列

题目:写一个函数,输入n,求斐波那契数列的第n项. 1 package Solution; 2 3 /** 4 * 剑指offer面试题9:斐波那契数列 5 * 题目:写一个函数,输入n,求斐波那契数列的第n项. 6 * 0, n=1 7 * 斐波那契数列定义如下:f(n)= 1, n=2 8 * f(n-1)+f(n-2), n>2 9 * @author GL 10 * 11 */ 12 public class No9Fibonacci { 13 14 public static void