leetcode
leetcode 1151 ~ 1200
统计元音字母序列的数目

统计元音字母序列的数目

难度:

标签:

题目描述

代码结果

运行时间: 50 ms, 内存: 16.0 MB


/*
 * 思路:
 * 使用流的方式处理相同的动态规划问题。
 * 虽然 Java Stream 并不完全适合复杂的动态规划问题,
 * 但我们可以使用它来简化一些操作,如初始化和求和。
 */
import java.util.stream.LongStream;

public class VowelPermutationStream {
    private static final int MOD = 1000000007;

    public int countVowelPermutation(int n) {
        long[] dpA = new long[n];
        long[] dpE = new long[n];
        long[] dpI = new long[n];
        long[] dpO = new long[n];
        long[] dpU = new long[n];

        // 初始化第一行
        dpA[0] = dpE[0] = dpI[0] = dpO[0] = dpU[0] = 1;

        LongStream.range(1, n).forEach(i -> {
            dpA[(int)i] = (dpE[(int)i-1] + dpI[(int)i-1] + dpU[(int)i-1]) % MOD;
            dpE[(int)i] = (dpA[(int)i-1] + dpI[(int)i-1]) % MOD;
            dpI[(int)i] = (dpE[(int)i-1] + dpO[(int)i-1]) % MOD;
            dpO[(int)i] = dpI[(int)i-1] % MOD;
            dpU[(int)i] = (dpI[(int)i-1] + dpO[(int)i-1]) % MOD;
        });

        long result = (dpA[n-1] + dpE[n-1] + dpI[n-1] + dpO[n-1] + dpU[n-1]) % MOD;
        return (int) result;
    }
}

解释

方法:

此题解运用了矩阵快速幂的方法来解决问题。首先定义一个转移矩阵 base,其中 base[i][j] 表示从元音 i 到元音 j 的合法转移数。初始向量 init 表示每个元音字符作为起始字符的情况数。题目的主要任务是计算 base 矩阵的第 n-1 次幂与 init 向量的乘积。使用矩阵快速幂可以有效地计算矩阵的高次幂,从而减少计算时间。矩阵快速幂通过不断将幂次折半,并在每次幂次为奇数时累乘当前结果,实现了对幂次的快速计算。最后,通过遍历结果向量的元素求和并取模,得到最终的答案。

时间复杂度:

O(log n)

空间复杂度:

O(1)

代码细节讲解

🦆
在定义转移矩阵base时,如何确定矩阵中各元素的值,特别是0和1的分布依据是什么?
转移矩阵base的各元素值确定基于题目规定的字符串生成规则。矩阵的每行表示一个特定的元音字符,每列也对应一个元音字符。矩阵中的元素base[i][j]表示从元音i到元音j的直接转移是否合法。如果按照题目的规则,元音i可以直接跟随元音j形成合法序列,则base[i][j]为1;否则为0。例如,如果元音'a'可以跟随'b'和'e',则矩阵中'a'行的'b'和'e'列的位置为1,其它为0。这种分布依据确保了每种元音字符转移的合法性被正确地表示在矩阵中。
🦆
矩阵快速幂的原理是什么,它如何减少计算次数来提高效率?
矩阵快速幂是快速幂算法的一种扩展,用于高效计算矩阵的n次幂。原理是通过将幂次分解为2的幂的和,从而减少乘法次数。具体来说,每次将幂次减半,如果当前幂次为奇数,则将当前矩阵乘到结果中。这种方法通过每次减半幂次,只需要进行对数次的矩阵乘法,相比直接进行n次矩阵乘法大大提高了效率。这对于大幂次的矩阵乘法尤为重要,因为直接计算会非常耗时。
🦆
在矩阵乘法函数mult中,为什么需要对结果进行mod操作,使用的模数`1000000007`有什么特殊意义?
在矩阵乘法函数mult中进行mod操作是为了避免计算过程中整数溢出,并保持结果的规模可控。使用的模数`1000000007`是一个大的质数,这具有几个优点:1) 在算法竞赛和实际应用中,使用大质数可以减少可能的哈希冲突;2) 在模运算下,质数能确保乘法操作在模数范围内形成一个有良好数学性质的数环,有助于避免计算中的不必要的数值问题。
🦆
请解释如何利用初始向量init和转移矩阵base来计算长度为n的字符串的总数目?
初始向量init表示每个元音字符作为起始字符的情况数,通常初始化为1。转移矩阵base表示各元音字符之间的合法转移次数。要计算长度为n的字符串总数目,我们利用矩阵快速幂计算base的n-1次幂,然后将这个结果矩阵乘以初始向量init。最终结果向量中的每个元素代表以对应元音字符结束的长度为n的字符串数目。将这些数目相加并取模,就得到了长度为n的所有可能字符串的总数目。

相关问题