leetcode
leetcode 1451 ~ 1500
统计字典序元音字符串的数目

统计字典序元音字符串的数目

难度:

标签:

题目描述

代码结果

运行时间: 21 ms, 内存: 16.1 MB


/* 
 * Problem: Given an integer n, return the number of strings of length n that can be formed using only vowels (a, e, i, o, u) and are lexicographically sorted. 
 * 
 * Approach: 
 * This problem can be solved using dynamic programming and Java streams. We maintain a 2D array dp where dp[i][j] represents the number of valid strings of length i that end with the j-th vowel. 
 * Transition: For each length i and each vowel j, dp[i][j] is the sum of all dp[i-1][k] where k <= j. This is because if a string ends with the j-th vowel, the previous character must be a vowel less than or equal to the j-th vowel to maintain lexicographical order. 
 * Base case: For strings of length 1, dp[1][j] is 1 for all j because each vowel is a valid string of length 1. 
 */ 
 
import java.util.stream.IntStream; 
 
public class VowelStringCountStream { 
    public int countVowelStrings(int n) { 
        int[][] dp = new int[n + 1][5]; 
        IntStream.range(0, 5).forEach(j -> dp[1][j] = 1); // Base case: strings of length 1 
        IntStream.range(2, n + 1).forEach(i -> 
            IntStream.range(0, 5).forEach(j -> 
                dp[i][j] = IntStream.rangeClosed(0, j).map(k -> dp[i-1][k]).sum() 
            ) 
        ); 
        return IntStream.range(0, 5).map(j -> dp[n][j]).sum(); 
    } 
} 

解释

方法:

这个题解利用了动态规划的方法来解决问题。首先,初始化一个数组 `pre` 表示长度为 1 的所有情况,每种元音字符各有一个。随后,定义一个 dp 数组来存储当前长度的字符串情况的组合数。变量 `sum_` 用来累加所有的组合数。对于每一个长度从 2 到 n,更新 dp 数组中的每个元素,其中 dp[j] 表示以第 j 个元音结尾的字符串的数量。这是通过累加从当前元音到最后一个元音的组合数来实现的,因为字符串必须按字典序排列。最终,累加所有长度为 n 的组合数得到答案。

时间复杂度:

O(n)

空间复杂度:

O(1)

代码细节讲解

🦆
在您的动态规划解法中,数组`pre`和`dp`的具体作用是什么,它们如何帮助计算长度为n的字符串数量?
`pre`数组用于存储前一次迭代中,以每个元音字母结尾的字符串的数量。`dp`数组在当前迭代中用同样的方式更新,表示当前长度的字符串数量。通过这种方式,`dp`数组在每一轮循环中根据`pre`数组的值进行更新,确保正确计算出以每个元音结尾的字符串数量,从而利用这些值计算出长度为n的所有字典序元音字符串的总数。
🦆
为什么在每次循环中更新`cnt`为`sum_`,`sum_`能准确反映什么信息?
`sum_`在每次迭代开始时存储了所有以任意元音结尾的字符串的总数。将`cnt`更新为`sum_`是为了在当前循环中为每个`dp[j]`计算新的字符串数。`sum_`因此反映了在当前长度下所有可能的字符串组合数,这是因为每次增加字符串长度时,新的字符串都可以在之前的所有字符串后追加任意元音。
🦆
在动态规划过程中,如何保证字符串是按字典序排列的?
在更新`dp`数组时,确保了字符串是按字典序排列的,因为对于每个元音`j`,`dp[j]`的更新是基于从`j`到最后一个元音的所有组合数。这意味着我们只计算那些以该元音或之后的元音结尾的字符串,保持了字典序的正确性。
🦆
您提到`将当前的dp复制到pre`,这一步为什么是必要的,直接使用dp数组不行吗?
在每轮迭代中,`dp`数组是基于`pre`数组计算而来的。如果不将`dp`复制到`pre`,则在下一次迭代中,`pre`数组的值将是未更新的,导致计算错误。复制确保了在每次迭代时,我们都有正确的前一状态的数据,从而可以准确计算当前状态。直接使用`dp`数组会导致计算过程中数据的覆盖,使得无法正确反映前一状态的信息。

相关问题