• 跳台阶问题(类似斐波那契数列)


    题目来源:https://leetcode.cn/problems/qing-wa-tiao-tai-jie-wen-ti-lcof/

    引言

    动态规划解法,时间复杂度为 O ( n ) O(n) O(n)
    使用矩阵乘法快速幂,时间复杂度为 O ( l o g n ) O(logn) O(logn)

    找规律

    n012345
    ans112358

    f ( n ) = { 1 , n = 0 , 1 f ( n − 2 ) + f ( n − 1 ) , n ≥ 2 f(n) =

    {1,n=0,1f(n2)+f(n1),n2" role="presentation">{1,n=0,1f(n2)+f(n1),n2
    f(n)={1,f(n2)+f(n1),n=0,1n2

    动态规划代码

    class Solution {
        public int numWays(int n) {
            int a = 1, b = 1, sum;
            for(int i = 0; i < n; i++){
                sum = (a + b) % 1000000007;
                a = b;
                b = sum;
            }
            return a;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    矩阵快速幂

    分析

    改写状态转移公式如下

    [ f ( n ) f ( n − 1 ) ] = [ 1 1 1 0 ] [ f ( n − 1 ) f ( n − 2 ) ]

    [f(n)f(n1)]" role="presentation">[f(n)f(n1)]
    =
    [1110]" role="presentation">[1110]
    [f(n1)f(n2)]" role="presentation">[f(n1)f(n2)]
    [f(n)f(n1)]=[1110][f(n1)f(n2)]

    以此类推…

    [ f ( n ) f ( n − 1 ) ] = [ 1 1 1 0 ] n − 1 [ f ( 1 ) f ( 0 ) ]

    [f(n)f(n1)]" role="presentation">[f(n)f(n1)]
    =
    [1110]" role="presentation">[1110]
    ^{n-1}
    [f(1)f(0)]" role="presentation">[f(1)f(0)]
    [f(n)f(n1)]=[1110]n1[f(1)f(0)]

    方阵乘法较为方便改写为如下情况。

    [ f ( n ) 0 f ( n − 1 ) 0 ] = [ 1 1 1 0 ] n − 1 [ f ( 1 ) 0 f ( 0 ) 0 ]

    [f(n)0f(n1)0]" role="presentation">[f(n)0f(n1)0]
    =
    [1110]" role="presentation">[1110]
    ^{n-1}
    [f(1)0f(0)0]" role="presentation">[f(1)0f(0)0]
    [f(n)f(n1)00]=[1110]n1[f(1)f(0)00]

    那么如何快速求得 [ 1 1 1 0 ] n

    [1110]" role="presentation">[1110]
    ^n [1110]n即为加速的关键

    快速幂

    将幂次 n n n改写为二进制形式来看,举例当 n = 5 n = 5 n=5时,改写为二进制 n = 0 b 101 n = 0b101 n=0b101
    那么 x 5 = x 2 2 ⋅ 1 ⋅ x 2 1 ⋅ 0 ⋅ x 2 0 ⋅ 1 x^5 = x^{2^2 \cdot 1} \cdot x^{2^1 \cdot 0} \cdot x^{2^0 \cdot 1} x5=x221x210x201
    快速幂即可从后往前遍历 n n n的二进制数每一位,每比特表示为有效位,每往左迭代1位,乘数平方1次。

    Java完整代码

    class Solution {
        static final int MOD = 1000000007;
    
        public int numWays(int n) {
            if (n < 2) {
                return 1;
            }
            int[][] base = {{1, 1}, {1, 0}};
            int[][] f1f0 = {{1, 1}, {0, 0}};
            int[][] answer = matrixMultiplication(f1f0, matrixPower(base, n - 1)) ;
            return answer[0][0];
        }
    
        public int[][] matrixPower(int[][] matrix, int n) {
            int[][] result = {{1, 0}, {0, 1}};
            while (n > 0) {
                if ((n & 1) == 1) {
                    result = matrixMultiplication(matrix, result);
                }
                n >>= 1;
                matrix = matrixMultiplication(matrix, matrix);
            }
            return result;
        }
    
        public int[][] matrixMultiplication(int[][] matrix1, int[][] matrix2) {
            int[][] result = new int[2][2];
            for (int i = 0; i < 2; ++i) {
                for (int j = 0; j < 2; ++j) {
                    result[i][j] = (int) ((
                            (long) matrix1[i][0] * matrix2[0][j] + (long) matrix1[i][1] * matrix2[1][j]
                    ) % MOD);
                }
            }
            return result;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
  • 相关阅读:
    21、阿里云oss
    爱情❤️终结者
    使用fastlane match自动化管理证书和描述文件
    c++类和对象(二)六个默认成员函数。
    TCP/IP网络江湖——数据链路层的协议与传承(数据链路层中篇:数据链路层的协议与帧)
    [JavaScript游戏开发] 2D二维地图绘制、人物移动、障碍检测
    基于亚马逊云科技 Serverless架构的实时数仓架构
    JavaScript面向对象学习(一)
    中国密码算法与NIST标准对比
    嵌入式学习板开发:STC单片机扑克游戏设计(C语言)
  • 原文地址:https://blog.csdn.net/Formy7/article/details/128063389