标签:fibonacci数列
1、解决方案
Fibonacci数列增长很快,第100个已经到了10的20次方,64位计算机才表示到19次方。所以这里统一采用计算第40个数来比较性能。实际上,4个字节的int类型只能计算到第48个Fibonacci数(以0、1、1、2开头)为1836 311 903,一个18亿左右的数字。
1)递归方法——写法简单,效率非常低下
public class Fibonacci { /** * @param args */ public static void main(String[] args) { // TODO 自动生成的方法存根 long start=System.nanoTime(); //获取开始时间 int fibonacciNO=getFibonacci(40); long end=System.nanoTime(); //获取结束时间 System.out.println("程序运行时间: "+(end-start)+"ns"); System.out.println(fibonacciNO); } /* 递归方案 */ public static int getFibonacci(int n) { if (n == 1) { return 0; } else if (n == 2) { return 1; } else { return getFibonacci(n - 1) + getFibonacci(n - 2); } } }******************************************************************
输出:程序运行时间: 687841156ns
63245986
2)动态规划方法——写法简单,非常高效,复杂度O(n)
思路:算法导论370页课后题15.1-5,符合动态规划的一个特性——当前问题调用了两个子问题。
public class Fibonacci { /** * @param args */ public static void main(String[] args) { // TODO 自动生成的方法存根 long start=System.nanoTime(); //获取开始时间 int[] fibonacciNO=getFibonacci(40); long end=System.nanoTime(); //获取结束时间 System.out.println("程序运行时间: "+(end-start)+"ns"); for (int i : fibonacciNO) { System.out.println(i); } } /*自底向上进行计算*/ public static int[] getFibonacci(int n) { int[] temp=new int[n]; temp[0]=0; temp[1]=1; for (int i = 2; i < n; i++) { temp[i]=temp[i-1]+temp[i-2]; } return temp; } }*****************************************
程序运行时间: 5131ns
63245986
3)通项公式方法——投机取巧,比较低效
思路:算法导论59页
public class Fibonacci { /** * @param args */ public static void main(String[] args) { // TODO 自动生成的方法存根 long start=System.nanoTime(); //获取开始时间 System.out.println(getFibonacci(40)); long end=System.nanoTime(); //获取结束时间 System.out.println("程序运行时间: "+(end-start)+"ns"); } public static int getFibonacci(int i) { float root=(float) ((1+Math.sqrt(5))/2); return (int) Math.round(Math.pow(root, i)/Math.sqrt(5)); } }*****************************************
控制台输出:
102334197
程序运行时间: 655532ns
2、相关的数学问题
1)排列组合
有一段楼梯有10级台阶,规定每一步只能跨一级或两级,要登上第10级台阶有几种不同的走法?
这就是一个斐波那契数列:登上第一级台阶有一种登法;登上两级台阶,有两种登法;登上三级台阶,有三种登法;登上四级台阶,有五种登法……
1,2,3,5,8,13……所以,登上十级,有89种走法。
2)数列中相邻两项的前项比后项的极限
当n趋于无穷大时,F(n)/F(n+1)的极限是多少?
这个可由它的通项公式直接得到,极限是(-1+√5)/2,这个就是黄金分割的数值,也是代表大自然的和谐的一个数字。
3、【一道面试题】如何判断一个数是不是Fibonacci数?(我的一点思路,还没有找到最终答案)
讨论区:http://bbs.csdn.net/topics/120067216
1)在数比较小的时候(小于20724)
A verynice test is that N is a Fibonacci number if and only if 5 n^2 + 4 or 5n^2 – 4 is a squarenumber.
即判断5 n^2 + 4 or 5n^2 – 4 是否是完全平方数,这里引出一个算法问题:“如何判断一个数是完全平方数?”,参考http://blog.sina.com.cn/s/blog_5a4882970102dxa5.html。这里主要讲完全平方数必然是连续奇数和:1+3+5+7+....+(2*n-1)=n^2。
public class Fibonacci { /** * @param args */ public static void main(String[] args) { // TODO 自动生成的方法存根 long start=System.nanoTime(); //获取开始时间 int[] fibonacciNO=getFibonacci(48); long end=System.nanoTime(); //获取结束时间 System.out.println("程序运行时间: "+(end-start)+"ns"); for (int i : fibonacciNO) { System.out.print(isFibonacciNo(i)); } } /*是否是Fibonacci数*/ public static boolean isFibonacciNo(int n) { /*5 n^2 + 4如果大于Integer.MAX_VALUE则表明无法做判断了*/ if (n>Math.pow((Integer.MAX_VALUE-4)/5, 0.5)) { System.out.print("无法判断——"); return false; } int temp=(int) (5*Math.pow(n, 2)); return isPerfectSquareNo(temp+4)||isPerfectSquareNo(temp-4); } /*完全平方数的判断*/ public static boolean isPerfectSquareNo(int n) { for (int i = 1; n >0; i+=2) { n-=i; } return n==0; } /*自底向上进行计算*/ public static int[] getFibonacci(int n) { int[] temp=new int[n]; temp[0]=0; temp[1]=1; for (int i = 2; i < n; i++) { temp[i]=temp[i-1]+temp[i-2]; } return temp; } }***********************************************
程序测试表明,4个字节的int类型能只能判断到(int)Math.pow((Integer.MAX_VALUE-4)/5, 0.5)),大约20724,即最多可以判断2万个数而已。
2)、在数字比较大的情况下(整个Int长度内判断)
思路1
使用动态规划方法生成Fibonacci数列,直到生成的Fibonacci数列等于n返回true,大于n返回false。
思路2
。。。。待续,绝对应该有比较高效的算法。。。。。
标签:fibonacci数列
原文地址:http://blog.csdn.net/brillianteagle/article/details/39029125