https://leetcode-cn.com/problems/number-of-substrings-containing-all-three-characters/
使用双指针,维护一个刚好满足条件的段,因为往左右扩展也会满足条件,所以扩展的数目为(左边的空余)*(右边的空余),为了避免先后出现重复,左边最多扩展到上次的左边。
class Solution {
public:
int numberOfSubstrings(string s) {
int cnts[3];
cnts[0]=cnts[1]=cnts[2]=0;
int i=0,j=0;
while(j<s.size()){
cnts[s[j]-'a']++;
if(cnts[0]>=1 && cnts[1]>=1 && cnts[2]>=1){
break;
}
j++;
}
while(cnts[s[i]-'a']>1){
cnts[s[i]-'a']--;
i++;
}
int sum=(i+1)*(s.size()-j);
int prev=i;
while(i<s.size()){
char c=s[i];
do{
cnts[s[i]-'a']--;
i++;
} while(s[i]==c && cnts[s[i]-'a']>1);
while( (cnts[0]==0 || cnts[1]==0 || cnts[2]== 0) && j+1 < s.size()){
j++;
cnts[s[j]-'a']++;
}
if(cnts[0]==0 || cnts[1]==0 || cnts[2]== 0)
break;
sum+=(i-prev)*(s.size()-j);
prev=i;
}
return sum;
}
};
这是一种固定左边,扩展右边,遍历所有位置作为左边位置的方法
class Solution {
public:
int numberOfSubstrings(string s) {
int cnts[3];
cnts[0]=cnts[1]=cnts[2]=0;
int i=0,j=-1;
int sum=0;
while(i<s.size()){
while( !(cnts[0]>=1 && cnts[1]>=1 && cnts[2]>=1)){
j++;
if(j>=s.size())
break;
cnts[s[j]-'a']++;
}
if( !(cnts[0]>=1 && cnts[1]>=1 && cnts[2]>=1))
break;
sum+=(s.size()-j);
cnts[s[i]-'a']--;
i++;
}
return sum;
}
};
本文详细解析了LeetCode上一道题目,即如何计算字符串中包含所有三种字符的所有子串数量。通过双指针技巧,算法在O(n)的时间复杂度内实现了高效求解。
509

被折叠的 条评论
为什么被折叠?



