矩阵快速幂<leetcode笔记>


矩阵快速幂


问题描述: 爬楼梯需要n阶可爬到楼顶,每次只能爬1或2阶,问共有多少种爬法。
动态规划: 由于每次只能爬1或2阶,故阶数为n的总方案数为最后一步爬1阶(即阶数为n-1阶的总方案数)加上最后一步爬2阶(即阶数为n-2阶的总方案数)。
可得,状态转移方程: f(n) = f(n - 1) + f(n -2); <斐波那契数列>
边界条件: f(0) = 1,f(1) = 1;
对此状态转移方程,可使用递归或迭代法:
递归:

class Solution{    //超出时间限制 !!!!
    public int climbStairs(int n){
        if(n == 0)   return 1;
        if(n == 1)   return 1;
        return  climbStairs(n - 1) + climbStairs(n - 2);
    }
}

迭代:

class Solution{    //执行用时:0ms,击败100%
                   //内存消耗:35.1MB,击败79.34%
    public int climbStairs(int n){
        int f0 = 1,f1 = 1,fx = 0;
        for(int i = 2;i <= n;i++){
            fx = f0 + f1;
            f0 = f1;
            f1  =fx;
        }
        if(n == 0 || n == 1)   return 1;
        return fx;
    }
}        //时间复杂度o(n),空间复杂度o(1)

矩阵快速幂:
在这里插入图片描述
在这里插入图片描述
不是所有的非齐次线性递推都可以转换为齐次线性递推!!!
矩阵快速幂原理: 通常计算矩阵A的n次幂高达o(n^3),运算效率极低,故应将n转换为二进制数
eg: 15 = (1111) = 1 * 2^3 + 1 * 2^2 + 1 * 2^1 + 1* 2^0;
关键代码:

public int[][] pow(int[][] a, int n) {
        int[][] ret = {{1, 0}, {0, 1}};   //定义单位阵
        while (n > 0) {
            if ((n & 1) == 1) {    //若n的二进制形式该位为1,则加入结果
                ret = multiply(ret, a);
            }
            n >>= 1;
            a = multiply(a, a);
        }
        return ret;
    }        

完整代码:

class Solution {
    public int climbStairs(int n) {
        int[][] p = {{1, 1}, {1, 0}};//齐次线性递推构造矩阵
        int[][] res = pow(p, n);
        return res[0][0];
    }

    public int[][] pow(int[][] a, int n) {
        int[][] ret = {{1, 0}, {0, 1}};
        while (n > 0) {
            if ((n & 1) == 1) {
                ret = multiply(ret, a);
            }
            n >>= 1;
            a = multiply(a, a);
        }
        return ret;
    }

    public int[][] multiply(int[][] a, int[][] b) {  //2阶矩阵相乘
        int[][] c = new int[2][2];
        for (int i = 0; i < 2; i++) {
            for (int j = 0; j < 2; j++) {
                c[i][j] = a[i][0] * b[0][j] + a[i][1] * b[1][j];
            }
        }
        return c;
    }
}          //时间复杂度:o(logn) 空间复杂度:o(1)

斐波那契数列通项公式:
在这里插入图片描述

class Solution{
    public int climbStairs(int n){
        double sqrt5 = Math.sqrt(5);
        double fibn = Math.pow((1+sqrt5)/2,n + 1) - Math.pow((1-sqrt5)/2,n + 1);
        return (int)Math.round(fibn/sqrt5);
    }
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值