Given an integer n, your task is to count how many strings of length n can be formed under the following rules:
- Each character is a lower case vowel (
'a','e','i','o','u') - Each vowel
'a'may only be followed by an'e'. - Each vowel
'e'may only be followed by an'a'or an'i'. - Each vowel
'i'may not be followed by another'i'. - Each vowel
'o'may only be followed by an'i'or a'u'. - Each vowel
'u'may only be followed by an'a'.
Since the answer may be too large, return it modulo 10^9 + 7.
Example 1:
Input: n = 1 Output: 5 Explanation: All possible strings are: "a", "e", "i" , "o" and "u".
Example 2:
Input: n = 2 Output: 10 Explanation: All possible strings are: "ae", "ea", "ei", "ia", "ie", "io", "iu", "oi", "ou" and "ua".
Example 3:
Input: n = 5 Output: 68
Constraints:
1 <= n <= 2 * 10^4
思路:
一开始觉得这题跟图有关,后来发现好像不太好算结果,就改用dp, 其实确定了方法,这题不麻烦,只是心里没底, 提交上去会不会超时。整体是这样的, 创建一个二维数组dp, dp[i]是一个长度为5的整数数组,dp[i][j]代表某个元音字母(a, e, i, o, u)在第i位上的计数。这样我们可以推导出下面的结论(字母与index的对应为a: 0, e: 1, i: 2, o: 3, u: 4):
能排在a之前的只有e, i, u, 所以dp[i][0] = dp[i-1][1] + dp[i-1][2] + dp[i-1][4]
能排在e之前的只有a, i, 所以dp[i][1] = dp[i-1][0] + dp[i-1][2]
能排在i之前的只有i, o, 所以dp[i][2] = dp[i-1][1] + dp[i-1][3]
能排在o之前的只有i, 所以dp[i][3] = dp[i-1][2]
能排在u之前的只有i, o, 所以dp[i][4] = dp[i-1][2] + dp[i-1][3]
代码:
const M: i64 = 1000000007;
impl Solution {
fn dp(n: usize, visited: &mut Vec<bool>, cache: &mut Vec<Vec<i64>>) -> Vec<i64> {
if n == 0 {
return vec![1, 1, 1, 1, 1];
}
if visited[n - 1] {
let prev = cache[n - 1].clone();
cache[n][0] = (prev[1] + prev[2] + prev[4]) % M;
cache[n][1] = (prev[0] + prev[2]) % M;
cache[n][2] = (prev[1] + prev[3]) % M;
cache[n][3] = prev[2] % M;
cache[n][4] = (prev[2] + prev[3]) % M;
visited[n] = true;
return cache[n].clone();
} else {
let prev = Solution::dp(n - 1, visited, cache);
cache[n][0] = (prev[1] + prev[2] + prev[4]) % M;
cache[n][1] = (prev[0] + prev[2]) % M;
cache[n][2] = (prev[1] + prev[3]) % M;
cache[n][3] = prev[2] % M;
cache[n][4] = (prev[2] + prev[3]) % M;
visited[n] = true;
return cache[n].clone();
}
}
pub fn count_vowel_permutation(n: i32) -> i32 {
let mut visited = vec![false; n as usize];
let mut cache = vec![vec![0; 5]; n as usize];
let l = Solution::dp(n as usize - 1, &mut visited, &mut cache);
(l.into_iter().sum::<i64>() % M) as i32
}
}
动态规划解决元音排列问题
这篇博客介绍了一个关于字符串排列的问题,具体是计算在给定长度下,遵循特定元音排列规则(如'a'只能跟着'e'等)的字符串数量。作者使用动态规划方法来解决这个问题,通过创建一个二维数组dp来存储每个位置上元音的数量,并根据规则进行转移。虽然担心可能的运行时间,但最终实现了有效解决方案。
1010

被折叠的 条评论
为什么被折叠?



