这题是7/4/2021英文站leetcode的每日一题, 想把自己的想法和思路记录下来.
题目:
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
思路:
看到题我的第一个想法是用backtracking,因为之前用backtracking做过其他permutation的题.但是看到数据量(1<=n<=2*10^4)我就放弃了,用backtracking做绝对超时. 于是根据提示,我的新想法是用动态规划去做.
重新梳理了题目之后发现需要返回的结果是总数,不是可能的permutation. 那么动态规划确实是一个很好的方法. 一开始的思路是用一个大小是(n,6)2d的array去存储所有可能解的数量, 每一行存储当前长度下(1 - n) 每个原音字母的所有permutation长度,前五个列分别代表五个元音字母,第六列存储最后的permutation总数之和。从1开始,每行每列根据array里先前的数值递增,直到长度为n。最后返回第六列所有数值之和%(10^9+7)。想的很美,但是在实现时问题不少。 例如每个元音的可能的permutation长度其实和本身之前的permuta长度并没有关系,每个元音生成permutation的方法也不一样。于是我放弃了这个方法。
参考完官方的解之后,我发现我的第一步是没错的,可以用类似的方法去解,但是需要将每一个元音的permutation长度分开,存储为5个长度为n的1d的array。参考官方解提供的每个元音与其他的元音序列的关系,每个元音序列的更新算式也就出来了
图1: 每个元音序列的关系 (https://leetcode.com/problems/count-vowels-permutation/solution/)
a的可能的序列 = e,i,和u的前一个序列的总和,因为他们后面可以跟a
e的可能的序列 = a,i的前一个序列的总和,因为他们后面可以跟e
以此类推。。。
在更新完这五个permutation的array之后,将他们最后的值相加,再%10*9+7就可以得到结果了
代码:(c++)
class Solution {
public:
int mod = 1000000007;
int countVowelPermutation(int n) {
vector<long> aCount(n,1);
vector<long> eCount(n,1);
vector<long> iCount(n,1);
vector<long> oCount(n,1);
vector<long> uCount(n,1);
for (int i=1; i < n; i++)
{
aCount[i] =(eCount[i-1]+iCount[i-1]+uCount[i-1])%mod;
eCount[i] = (aCount[i-1]+iCount[i-1])%mod;
iCount[i] = (eCount[i-1]+oCount[i-1])%mod;
oCount[i] = (iCount[i-1])%mod;
uCount[i] = (iCount[i-1]+oCount[i-1])%mod;
}
long res = (aCount[n-1]+eCount[n-1]+iCount[n-1]+oCount[n-1]+uCount[n-1])%mod;
return (int)res;
}
};
结果: