矩阵快速求幂

今天看《剑指offer》看到一个递推关系:f(n) = f(n-1) + f(n-2). 书中提出了一种简单的算法,也就是矩阵乘法:

如果是n次方,那么时间复杂度应该是O(n). 那么有没有一种更快的算法呢?快速幂算法能让时间复杂度降至O(logn).

怎么来做快速幂算法呢?我们首先先想一个简单的,一个数字a,求他的75次幂。75的二进制是1001011 ,所以实际上a^75 = a^64 * a^8 * a^2 *a^1.  我们把它分解成整数指数次幂的积的形式。怎么乘呢?

        int a = 4, m = 75;
        int power2num = n;
        int result = 1;
        while(m != 0) {
            // 只有当最低位为1时,结果才乘上现在的值,
            if ((m & 1) != 0)
                result *= power2num;//这模拟的是a^t,t是二进制m中为1的位
            // 每移位一次,幂方计算一次
            power2num *= power2num;
            m >>= 1;
        }

看明白了吧,result模拟的是每个75中为1的位所代表的的a^t这一位。每次移位power2num都需要乘以自己。

 

那么矩阵是同理的。我们这里写了两个函数,一个单独处理矩阵的乘法,另一个是求幂:

    public long[][] matrixMult(long[][] a, long[][] b) {//求矩阵乘法
        // a的列必须与b的行相等
        assert a.length == b[0].length;
        int n = a.length, m = a[0].length, p = b[0].length;
        long[][] result = new long[n][p];
        //矩阵乘法的基本方式为三层循环
        for(int i=0; i<n; i++) {
            for(int j=0; j<p; j++) {
                for(int k=0; k<m; k++) {
                    result[i][j] += a[i][k] * b[k][j];
                }
            }
        }
        return result;
    }
    public long[][] matrixPower(long[][] matrix, int p) {//求幂函数
        //result存放结果,注意m*n x n*t的矩阵维度结果是m*t
        long[][] result = new long[matrix.length][matrix[0].length];

        for(int i=0; i<result.length; i++) {//result先是全1矩阵
            result[i][i] = 1;
        }

        long[][] pingfang = matrix;//复制matrix
        for(; p != 0; p >>= 1) {
            if((p & 1) != 0) {
                // 注意result在前面
                result = matrixMult(result, pingfang);
            }
            pingfang = matrixMult(pingfang, pingfang);
        }
        return result;
    }

通过这两个函数就可以迅速求出一个矩阵的n次方了。斐波那契数列那道题,这个2x2矩阵应该是【11】

                                                                                                                                                        【10】

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值