力扣刷题——3306. 元音辅音字符串计数 II
好久没搞刷题了,搞副业搞晕了。。。
看到题的第一感觉是滑动窗口,直接开写。
class Solution
{
public:
int countOfSubstrings(string word, int k)
{
vector<int> cnt(26, 0);
int left = 0, right = 0;
int res = 0;
while (right < word.size())
{
cnt[word[right] - 'a']++;
int tem = check(cnt);
if (tem == -1)
{
right++;
continue;
}
if (right - left + 1 - tem > k)
{
cnt[word[left] - 'a']--;
cnt[word[right] - 'a']--;
left++;
continue;
}
if (right - left + 1 - tem == k)
{
res++;
}
right++;
}
cnt[word[left] - 'a']--;
left++;
right--;
while (true)
{
int tem = check(cnt);
if (tem == -1)
break;
if (right - left + 1 - tem < k)
break;
if (right - left + 1 - tem == k)
{
res++;
}
cnt[word[left] - 'a']--;
left++;
}
return res;
}
int check(vector<int> &cnt)
{
if (cnt['a' - 'a'] == 0 || cnt['e' - 'a'] == 0 || cnt['i' - 'a'] == 0 || cnt['o' - 'a'] == 0 || cnt['u' - 'a'] == 0)
return -1;
int tem = cnt['a' - 'a'] + cnt['e' - 'a'] + cnt['i' - 'a'] + cnt['o' - 'a'] + cnt['u' - 'a'];
return tem;
}
};
调整了好几遍,结果写了一坨。。。关键还是没有过。。。
重新看了一遍上边的代码,感觉槽点太多了,本来是个左闭右开的滑动窗口,结果写的乱七八糟。回到问题上,在对用例word = "ieiaoud", k = 0分析了一下之后,发现只用一个滑动窗口难以解决这个问题,看了下题解,用两个滑动窗口就能够很好的解决。
核心思路再写一个函数sub(k),能够输出满足子串中非元音字母数>=k的子串数量,这样最终答案就是用sub(k) - sub(k + 1),实现如下:
class Solution
{
public:
long long countOfSubstrings(string word, int k)
{
return sub(word, k) - sub(word, k + 1);
}
long long sub(string &word, int k)
{
int n = word.size();
int left = 0, right = 0;
vector<int> cnt(26, 0);
long long res = 0;
while (left < n)
{
while (right < n && (right - left - check(cnt) < k || check(cnt) == -1))
{
cnt[word[right] - 'a']++;
right++;
}
if ((right - left - check(cnt)) >= k && check(cnt) != -1)
{
// 以[left...right]为前缀的子串都满足
res += n - right + 1;
}
cnt[word[left] - 'a']--;
left++;
}
return res;
}
int check(vector<int> &cnt)
{
if (cnt['a' - 'a'] == 0 || cnt['e' - 'a'] == 0 || cnt['i' - 'a'] == 0 || cnt['o' - 'a'] == 0 || cnt['u' - 'a'] == 0)
return -1;
int tem = cnt['a' - 'a'] + cnt['e' - 'a'] + cnt['i' - 'a'] + cnt['o' - 'a'] + cnt['u' - 'a'];
return tem;
}
};

浙公网安备 33010602011771号