zoukankan      html  css  js  c++  java
  • 每天一道算法题(30)——高效的求斐波拉契数列

             对于斐波拉契经典问题,我们都非常熟悉,通过递推公式F(n) = F(n - 1) + F(n - 2),我们可以在线性时间内求出第n项F(n),现在考虑斐波拉契的加强版,我们要求的项数n的范围为int范围内的非负整数,请设计一个高效算法,计算第n项F(n)。第一个斐波拉契数为F(0) = 1。给定一个非负整数,请返回斐波拉契数列的第n项,为了防止溢出,请将结果Mod 1000000007。

             或者,现在有一栋高楼,但是电梯却出了故障,无奈的你只能走楼梯上楼,根据你的腿长,你一次能走1级或2级楼梯,已知你要走n级楼梯才能走到你的目的楼层,请计算你走到目的楼层的方案数,由于楼很高,所以n的范围为int范围内的正整数。

    给定楼梯总数n,请返回方案数。为了防止溢出,请返回结果Mod 1000000007的值。


    1.递归    时间复杂度O(2^n)

    [java] view plaincopy
    1. int f(int n){  
    2.     if(n == 1 || n == 2){  
    3.         return 1;  
    4.     }  
    5.     return f(n-1) + f(n-2);  
    6. }  

    2.循环    时间复杂度O(n)

    [java] view plaincopy
    1. public int f(int n) {  
    2.     // write code here  
    3.     int f0 = 1;  
    4.     int f1 = 1;  
    5.     int f2 = 0;  
    6.   
    7.     for(int i = 2; i < n; i++){  
    8.         f2 = f0 + f1;  
    9.         f0 = f1;  
    10.         f1 = f2;  
    11.     }  
    12.     return f2;  
    13. }  

    3.矩阵求解    时间复杂度O(logn)

        斐波那契的递推公式可以表示成如下矩阵形式:

         根据矩阵的分治算法,可以在O(logn)时间内算出结果。

    public class Fibonacci {
    	static long[][] f = new long[][]{{0,1},{1,1}};  
    	public int getNthNumber(int n) {  
    	    if(n == 0)  
    	        return 1;  
    	    if(n == 1)  
    	        return 1;  
    	    f = pow(n,f);  
    	      
    	    return (int) (f[1][1]%1000000007);  
    	}  
    	  
    	private long[][] pow(int n,long[][] f){//矩阵的幂函数 
    	    if(n == 1)  
    	        return f;            
    	    if(n == 2)
    	        return fun(f,f);   
    	  
    	    if((n&1)==0){//偶数  
    	        f = pow(n/2,f);  
    	        return fun(f, f);  
    	    }
    	    else 
    	        return fun(pow(n/2,f),pow(n/2 + 1,f));   
    	}  
    	  
    	private long[][] fun(long[][] f,long[][] m){  
    	    long[][] temp = new long[2][2];  
    	    temp[0][0] = (f[0][0]*m[0][0] + f[0][1]*m[1][0]);
    	    temp[0][1] = (f[0][0]*m[0][1] + f[0][1]*m[1][1]);  
    	    temp[1][0] = (f[1][0]*m[0][0] + f[1][1]*m[1][0]);  
    	    temp[1][1] = (f[1][0]*m[0][1] + f[1][1]*m[1][1])%1000000007;  
    	    return temp;  
    	}  
    }





  • 相关阅读:
    test
    ws318 配置
    电影地址:
    白岩松给青少年的7个忠告,值得好好阅读~
    干部带队伍的四个知道,一个跟上
    CDOJ 1259 昊昊爱运动 II bitset+线段树
    codeforces 508D . Tanya and Password 欧拉通路
    poj 1041 John's trip 欧拉回路
    poj 1651 Multiplication Puzzle 区间dp
    poj 2955 Brackets 区间dp
  • 原文地址:https://www.cnblogs.com/engineerLF/p/5392991.html
Copyright © 2011-2022 走看看