O(logn)时间复杂度求Fibonacci数列(java)

来源:互联网 发布:程序员是吃青春饭的吗 编辑:程序博客网 时间:2024/04/25 18:36
package july37;/**题目:O(logn)时间复杂度求Fibonacci数列 *  * O(logn)时间复杂度求Fibonacci数列 *  *  * 下面介绍一种时间复杂度是O(logn)的方法。在介绍这种方法之前,先介绍一个数学公式: *{f(n), f(n-1), f(n-1), f(n-2)} ={1, 1, 1,0}n-1 *(注:{f(n+1), f(n), f(n), f(n-1)}表示一个矩阵。在矩阵中第一行第一列是f(n+1),第一行第二列是f(n),第二行第一列是f(n),第二行第二列是f(n-1)。) *有了这个公式,要求得f(n),我们只需要求得矩阵{1, 1, 1,0}的n-1次方,因为矩阵{1, 1, 1,0}的n-1次方的结果的第一行第一列就是f(n)。这个数学公式用数学归纳法不难证明。感兴趣的朋友不妨自己证明一下。 *现在的问题转换为求矩阵{1, 1, 1, 0}的乘方。如果简单第从0开始循环,n次方将需要n次运算,并不比前面的方法要快。但我们可以考虑乘方的如下性质: *        /  an/2*an/2                      n为偶数时 *an= *        \  a(n-1)/2*a(n-1)/2*a1            n为奇数时 *要求得n次方,我们先求得n/2次方,再把n/2的结果平方一下。如果把求n次方的问题看成一个大问题,把求n/2看成一个较小的问题。这种把大问题分解成一个或多个小问题的思路我们称之为分治法。这样求n次方就只需要logn次运算了。 *实现这种方式时,首先需要定义一个2×2的矩阵,并且定义好矩阵的乘法以及乘方运算。当这些运算定义好了之后,剩下的事情就变得非常简单。完整的实现代码如下所示。 * @author 牵手无奈 * */public class Fibonacci_logN {public static void main(String[] args) {// TODO Auto-generated method stubfor(int i=1;i<10;i++){System.out.println(fibonacci_logN(i)[0][1]);}}/**求第n个fibonacci数 * @param n * @return */public static int[][] fibonacci_logN(int n){if(n<=1){return new int[][]{{1,1},{1,0}};}else if((n&1)==0){int[][] temp = fibonacci_logN(n/2);temp = calMatrix(temp, temp);return temp;}else {int[][] temp = fibonacci_logN(n/2);temp = calMatrix(temp, temp);temp = calMatrix(temp, new int[][]{{1,1},{1,0}});return temp;}}/**计算两个2*2的矩阵 * @param matrix1 * @param matrix2 * @return */public static int[][] calMatrix(int[][] matrix1,int[][] matrix2){int[][] result = new int[2][2];result[0][0]=matrix1[0][0]*matrix2[0][0] + matrix1[0][1]*matrix2[1][0];result[0][1]=matrix1[0][0]*matrix2[0][1] + matrix1[0][1]*matrix2[1][1];result[1][0]=matrix1[1][0]*matrix2[0][0] + matrix1[1][1]*matrix2[1][0];result[1][1]=matrix1[1][0]*matrix2[0][1] + matrix1[1][1]*matrix2[1][0];return result;}}

0 0
原创粉丝点击