Medium
题目描述
给你一个整数 n 。
如果一个字符串 s 只包含小写英文字母,并且可以重新排列 s 的字符得到包含 "leet" 作为子字符串的新字符串,那么我们称字符串 s 是 好的 。
例如:
- 字符串
"lteer"是好的,因为我们可以重新排列得到"leetr"。 "letl"不是好的,因为我们无法重新排列它来包含"leet"作为子字符串。
返回长度为 n 的好字符串的总数。
由于答案可能很大,请返回对 10^9 + 7 取余的结果。
子字符串是字符串中字符的连续序列。
示例 1:
输入:n = 4
输出:12
解释:可以重新排列得到包含 "leet" 作为子字符串的 12 个字符串是:"eelt", "eetl", "elet", "elte", "etel", "etle", "leet", "lete", "ltee", "teel", "tele", 和 "tlee"。
示例 2:
输入:n = 10
输出:83943898
解释:长度为 10 且可以重新排列得到包含 "leet" 作为子字符串的字符串数目是 526083947580。因此答案是 526083947580 % (10^9 + 7) = 83943898。
提示:
1 <= n <= 10^5- 好字符串必须包含至少一个
l、一个t和两个e。 - 将问题分解为子问题并使用动态规划。
解题思路
解题思路
这道题的关键是理解什么样的字符串可以重新排列得到包含 “leet” 的字符串。
要包含子字符串 “leet”,字符串必须至少包含:
- 至少 1 个字母 ’l'
- 至少 2 个字母 ’e'
- 至少 1 个字母 ’t'
我们可以使用容斥原理来解决这个问题:
- 首先计算所有可能的字符串总数:
26^n - 然后减去不满足条件的字符串数量
设:
- A = 缺少字母 ’l’ 的字符串集合
- B = 缺少字母 ’e’(少于2个)的字符串集合
- C = 缺少字母 ’t’ 的字符串集合
根据容斥原理:
好字符串数 = 总数 - |A∪B∪C|
= 26^n - |A| - |B| - |C| + |A∩B| + |A∩C| + |B∩C| - |A∩B∩C|
其中:
- |A| = 不包含 ’l’ 的字符串数 =
25^n - |C| = 不包含 ’t’ 的字符串数 =
25^n - |B| = 包含少于2个 ’e’ 的字符串数 =
25^n + n×25^(n-1)(0个e + 恰好1个e) - |A∩B|、|A∩C|、|B∩C|、|A∩B∩C| 类似计算
这种方法时间复杂度为 O(log n),空间复杂度为 O(1),是最优解法。
另一种思路是动态规划,但会更复杂一些,时间复杂度为 O(n)。
代码实现
class Solution {
public:
int stringCount(int n) {
const int MOD = 1e9 + 7;
auto power = [&](long long base, int exp) {
long long result = 1;
base %= MOD;
while (exp > 0) {
if (exp & 1) result = (result * base) % MOD;
base = (base * base) % MOD;
exp >>= 1;
}
return result;
};
long long total = power(26, n);
// 缺少 l 的字符串
long long no_l = power(25, n);
// 缺少 t 的字符串
long long no_t = power(25, n);
// e 少于 2 个的字符串:0个e + 1个e
long long less_e = (power(25, n) + (1LL * n * power(25, n-1)) % MOD) % MOD;
// 缺少 l 且 e 少于 2 个
long long no_l_less_e = (power(24, n) + (1LL * n * power(24, n-1)) % MOD) % MOD;
// 缺少 l 且缺少 t
long long no_l_no_t = power(24, n);
// 缺少 t 且 e 少于 2 个
long long no_t_less_e = (power(24, n) + (1LL * n * power(24, n-1)) % MOD) % MOD;
// 缺少 l、t 且 e 少于 2 个
long long no_l_no_t_less_e = (power(23, n) + (1LL * n * power(23, n-1)) % MOD) % MOD;
long long result = total - no_l - no_t - less_e + no_l_less_e + no_l_no_t + no_t_less_e - no_l_no_t_less_e;
result = ((result % MOD) + MOD) % MOD;
return result;
}
};
class Solution:
def stringCount(self, n: int) -> int:
MOD = 10**9 + 7
def power(base, exp):
result = 1
base %= MOD
while exp > 0:
if exp & 1:
result = (result * base) % MOD
base = (base * base) % MOD
exp >>= 1
return result
total = power(26, n)
# 缺少 l 的字符串
no_l = power(25, n)
# 缺少 t 的字符串
no_t = power(25, n)
# e 少于 2 个的字符串:0个e + 1个e
less_e = (power(25, n) + n * power(25, n-1)) % MOD
# 缺少 l 且 e 少于 2 个
no_l_less_e = (power(24, n) + n * power(24, n-1)) % MOD
# 缺少 l 且缺少 t
no_l_no_t = power(24, n)
# 缺少 t 且 e 少于 2 个
no_t_less_e = (power(24, n) + n * power(24, n-1)) % MOD
# 缺少 l、t 且 e 少于 2 个
no_l_no_t_less_e = (power(23, n) + n * power(23, n-1)) % MOD
result = total - no_l - no_t - less_e + no_l_less_e + no_l_no_t + no_t_less_e - no_l_no_t_less_e
return (result % MOD + MOD) % MOD
public class Solution {
public int StringCount(int n) {
const int MOD = 1000000007;
long Power(long baseNum, int exp) {
long result = 1;
baseNum %= MOD;
while (exp > 0) {
if ((exp & 1) == 1) result = (result * baseNum) % MOD;
baseNum = (baseNum * baseNum) % MOD;
exp >>= 1;
}
return result;
}
long total = Power(26, n);
// 缺少 l 的字符串
long no_l = Power(25, n);
// 缺少 t 的字符串
long no_t = Power(25, n);
// e 少于 2 个的字符串:0个e + 1个e
long less_e = (Power(25, n) + ((long)n * Power(25, n-1)) % MOD) % MOD;
// 缺少 l 且 e 少于 2 个
long no_l_less_e = (Power(24, n) + ((long)n * Power(24, n-1)) % MOD) % MOD;
// 缺少 l 且缺少 t
long no_l_no_t = Power(24, n);
// 缺少 t 且 e 少于 2 个
long no_t_less_e = (Power(24, n) + ((long)n * Power(24, n-1)) % MOD) % MOD;
// 缺少 l、t 且 e 少于 2 个
long no_l_no_t_less_e = (Power(23, n) + ((long)n * Power(23, n-1)) % MOD) % MOD;
long result = total - no_l - no_t - less_e + no_l_less_e + no_l_no_t + no_t_less_e - no_l_no_t_less_e;
return (int)((result % MOD + MOD) % MOD);
}
}
/**
* @param {number} n
* @return {number}
*/
var stringCount = function(n) {
const MOD = 1e9 + 7;
function power(base, exp) {
let result = 1;
base %= MOD;
while (exp > 0) {
if (exp & 1) result = (result * base) % MOD;
base = (base * base) % MOD;
exp >>= 1;
}
return result;
}
const total = power(26, n);
// 缺少 l 的字符串
const no_l = power(25, n);
// 缺少 t 的字符串
const no_t = power(25, n);
// e 少于 2 个的字符串:0个e + 1个e
const less_e = (power(25, n) + (n * power(25, n-1)) % MOD) % MOD;
// 缺少 l 且 e 少于 2 个
const no_l_less_e = (power(24, n) + (n * power(24, n-1)) % MOD) % MOD;
// 缺少 l 且缺少 t
const no_l_no_t = power(24, n);
// 缺少 t 且 e 少于 2 个
const no_t_less_e = (power(24, n) + (n * power(24, n-1)) % MOD) % MOD;
// 缺少 l、t 且 e 少于 2 个
const no_l_no_t_less_e = (power(23, n) + (n * power(23, n-1)) % MOD) % MOD;
let result = total - no_l - no_t - less_e + no_l_less_e + no_l_no_t + no_t_less_e - no_l_no_t_less_e;
return ((result % MOD) + MOD) % MOD;
};
复杂度分析
| 复杂度 | 大O表示法 |
|---|---|
| 时间复杂度 | O(log n) |
| 空间复杂度 | O(1) |
相关题目
- . Count Vowels Permutation (Hard)