好久没搞刷题了,搞副业搞晕了。。。
看到题的第一感觉是滑动窗口,直接开写。
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;}
};