LeetCode每日一题(Count Vowels Permutation)

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
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值