矩阵快速幂求斐波那契数列第n项

原理:

斐波那契数列定义

用矩阵形式来描述递推关系:

以上递推式可以写成矩阵形式:

观察结果

例如F(2) = 1, F(3) = 2...

 

而实际上f(n)就是矩阵的左上角元素就是斐波那契数列的第n项的值 

此矩阵指下面的递推关系矩阵

 普通的乘方算法

现在讨论矩阵的乘方。我们举一个例子,计算 A^10 。通常的运算是这样的:

A*A*A*A*A*A*A*A*A*A

我们发现,上述方法需要使用 9 次乘法运算才能够算出 A^10。一般而言,为计算A^10 ,用上述方法需要 N−1 次乘法才可以。那能不能改进呢?

快速幂算法

我们采用二分的策略优化它。具体如下所示:

T1=A*A;        //此时算到A^2
T2=T1*T1;      //此时算到A^4
T3=T2*T2;      //此时算到A^8
T4=T3*T1;      //此时算到A^10,结束,返回T4

我们发现,按照这种方法去计算,仅仅用了 4 次乘法运算就能算出 A^10 。

我们把如上算法一般化。 下面使用自顶向下的递归方法:

计算 A^n:
    设M=A^(n/2);    //其中n/2向下取整
    如果n=1:
        返回递推关系矩阵 (1,1,1,0)
    如果n是偶数: 
        返回M*M;
    如果n是奇数:
        返回M*M*M;

递归与矩阵快速幂的总结

1. 递归方法:

优点:

  • 实现简单,直观,易于理解。
  • 适用于小规模问题,对于小输入可以快速计算。

缺点:

  • 递归会产生大量重复计算,效率较低。
  • 时间复杂度为 (O(2^n)),指数级增长,导致性能在 (n) 增加时急剧下降。
  • 对于大规模输入,递归可能会导致堆栈溢出。
2. 矩阵快速幂方法:

优点:

  • 提高了计算效率,特别适用于大规模问题。
  • 时间复杂度为 (O(\log n)),具有较高的效率。
  • 避免了重复计算,提高了性能。

缺点:

  • 实现稍复杂,需要理解矩阵乘法和矩阵幂的算法。
3.比较总结:
  • 在小规模问题上,递归可能更直观,但在大规模问题上,矩阵快速幂明显更快。
  • 矩阵快速幂通过降低时间复杂度解决了递归中的重复计算问题,大大提高了效率。
  • 递归通常更易实现,但可能会受到堆栈溢出和指数级增长的时间复杂度影响。
  • 根据问题规模选择适当的方法,对于斐波那契数列等递推问题,矩阵快速幂是更为高效的选择。

完整代码: 

import java.time.Instant;


public class Fibonacci {
    public static void main(String[] args) {

        final Instant startTime = Instant.now();
        int n = 40; // 更改为您要查找的斐波那契数列的位置
        long result = fibonacciMatrix(n);
        final Instant endTime = Instant.now();
        System.out.println("第 " + n + " 位斐波那契数是:" + result);
        System.out.println("耗时:" +  (endTime.toEpochMilli() - startTime.toEpochMilli()) + " ms");
    }

    // 定义一个2x2的矩阵类
    static class Matrix {
        long a, b, c, d;

        Matrix(long a, long b, long c, long d) {
            this.a = a;
            this.b = b;
            this.c = c;
            this.d = d;
        }

        // 矩阵相乘
        Matrix multiply(Matrix other) {
            long newA = a * other.a + b * other.c;
            long newB = a * other.b + b * other.d;
            long newC = c * other.a + d * other.c;
            long newD = c * other.b + d * other.d;
            return new Matrix(newA, newB, newC, newD);
        }

        @Override
        public String toString() {
            return "Matrix:\n" +
                    "|" + a +
                    ", " + b +" |"+
                    "\n|" + c +
                    ", " + d +" |";
        }
    }

    // 快速幂算法计算斐波那契数列
    public static long fibonacciMatrix(int n) {
        if (n <= 1) {
            return n;
        }
        Matrix result = power(new Matrix(1, 1, 1, 0), n - 1);
        System.out.println(result.toString());
        return result.a;
    }

    // 快速幂算法
    private static Matrix power(Matrix matrix, int n) {
        if (n == 1) {
            return matrix;
        }
        if (n % 2 == 0) {
            Matrix half = power(matrix, n / 2);
            return half.multiply(half);
        } else {
            Matrix half = power(matrix, n / 2);
            return matrix.multiply(half).multiply(half);
        }
    }
}

当然如果需要求更大位数的值时,需要使用java的大数类去运算,否则会超出界限 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值