LeetCode 1358 包含所有三种字符的子串数目
🟡 中等 https://leetcode.cn/problems/number-of-substrings-containing-all-three-characters/description/
传统滑窗
这是收集 左边开始到i的数组个数。
class Solution {
public:
int numberOfSubstrings(string s) {
unordered_map<char,int> hash_map;
int left = 0;
int res = 0;
for(int i = 0;i<s.size();i++){
hash_map[s[i]]++;
while(hash_map.size()>=3){
hash_map[s[left]]--;
if(hash_map[s[left]]==0) hash_map.erase(s[left]);
left++;
}
res+=(left-1)-0+1;
}
return res;
}
};
也可以收集 left 到结束的子数组个数。
class Solution {
public:
int numberOfSubstrings(string s) {
unordered_map<char,int> hash_map;
int left = 0;
int res = 0;
for(int i = 0;i<s.size();i++){
hash_map[s[i]]++;
while(hash_map.size()>=3){
res+=s.size()-1-i+1;
hash_map[s[left]]--;
if(hash_map[s[left]]==0) hash_map.erase(s[left]);
left++;
}
}
return res;
}
};
动规
思考以 i 结尾的答案,其开始位置取决于 a b c 其中最晚出现位置的最小值。
使用 last数组维护上次 a b c 出现的最后位置。
首先last初始不能为0,那么设置成什么呢?-2可以吗?可以,但是要额外设置判断条件。可以设置成-1,假设最小的下标为 i,那么答案因该加 i+1, 所以我们要让初始abc都没更新时,答案的更新为0,因此令 i+1 = 0,i= -1,所以初始设置last 为-1.
class Solution {
public:
int numberOfSubstrings(string s) {
int last[3];
fill(last,last+3,-1);
int res = 0;
for(int i = 0;i<s.size();i++){
last[s[i]-'a'] = i;
int left = min(last[0],min(last[1],last[2]));
res+=left-(-1);
}
return res;
}
};