一、1358. 包含所有三种字符的子字符串数目
class Solution {
public:int numberOfSubstrings(string s) {int left = 0, ans = 0;vector<int> count(3, 0); // 用数组代替 unordered_map,索引 0 对应 'a', 1 对应 'b', 2 对应 'c'for (int right = 0; right < s.size(); ++right) {count[s[right] - 'a']++; // 更新当前字符的计数// 检查窗口是否满足条件while (count[0] > 0 && count[1] > 0 && count[2] > 0) {ans += s.size() - right; // 计算以当前 right 为右边界的所有符合条件的子字符串数量count[s[left] - 'a']--; // 收缩左边界left++;}}return ans;}
};
1.基本模型是:遍历 -> 维护 -> 计算(累加)
二、2962. 统计最大元素出现至少 K 次的子数组
class Solution {
public:long long countSubarrays(vector<int>& nums, int k) {int maxnum = 0;for(int num : nums){maxnum = maxnum > num ? maxnum : num; }int left = 0;long long ans = 0;int cntMaxnum = 0;for(int right = 0; right < nums.size(); right++){if(nums[right] == maxnum){cntMaxnum++;}while(cntMaxnum >= k){ans += nums.size() - right;if(nums[left] == maxnum){cntMaxnum--;}left++;}}return ans;}
};
三、3325. 字符至少出现 K 次的子字符串 I
class Solution {
public:int numberOfSubstrings(string s, int k) {int ans = 0, left = 0, cnt[26]{};for (char c : s) {cnt[c - 'a']++;while (cnt[c - 'a'] >= k) {cnt[s[left] - 'a']--;left++;}ans += left;}return ans;}
};
1. 思路和前两题差不多,这里尝试了换一种写法。把 ans += size - right 变成了 ans += left 。这样有个好处是方便写for(char c : s)循环,少设置一个right变量。
2.为什么只需判断 cnt[c - 'a'] >= k?
因为只有 cnt[c - 'a']++ 导致了 cnt[c - 'a'] 达到 k,所以其余字母的出现次数必然小于 k,无需判断。当然,这里的 >= 写成 == 也是可以的。