6069. 最大波动的子字符串
字符串的 波动 定义为子字符串中出现次数 最多 的字符次数与出现次数 最少 的字符次数之差。
给你一个字符串 s ,它只包含小写英文字母。请你返回 s 里所有 子字符串的 最大波动 值。
子字符串 是一个字符串的一段连续字符序列。
示例 1:
输入:s = “aababbb”
输出:3
解释: 所有可能的波动值和它们对应的子字符串如以下所示:
- 波动值为 0 的子字符串:“a” ,“aa” ,“ab” ,“abab” ,“aababb” ,“ba” ,“b” ,“bb” 和 “bbb” 。
- 波动值为 1 的子字符串:“aab” ,“aba” ,“abb” ,“aabab” ,“ababb” ,“aababbb” 和 “bab” 。
- 波动值为 2 的子字符串:“aaba” ,“ababbb” ,“abbb” 和 “babb” 。
- 波动值为 3 的子字符串 “babbb” 。 所以,最大可能波动值为 3 。
示例 2:
输入:s = “abcde”
输出:0
解释: s 中没有字母出现超过 1 次,所以 s 中每个子字符串的波动值都是 0 。
提示:
1 <= s.length <= 1e4
s 只包含小写英文字母。
解析
- 枚举每个最大最小值,像这种字符为26小写字母,很多都有枚举的做法。
- 序列中需要同时包含最大 ,最小字符。不能没有最小字符情况。
- 我们可以设定,只有遇到最小字符时才可以计算最大c1, 最小c2的差,可以怎么做呢? 用一个变量cntc2记录最大最小的差值,如果没有遇到c2就将两者差值cntc2设置为一个小于0的数(返回值是>=0)
- 还需要一个变量cntc1,在遇到c2之前,或者遇到下一个c2之前记录c1,c2两者的最大差,以至于在遇到下一个c2 时得到两者的差。
- 为什么cntc1的值最小为0? 例如abbaab,cntc1更确切的表示为:前边所有字符中a - b的最大差,为下一次遇到b做准备。
例如:aabaab, 最大为a, 最小为b;遇到第一个b之前cntc2=2,遇到b,cntc2=1,这时就能给cntc1赋值了(之前一直为INT_MIN),cntc1=cntc1=1;遇到第二个b了,cntc2=3,cntc1=cntc2=3;
class Solution {
public:
// meijv
int check(char c1,char c2,string s){
int n=s.size();
int cntc1=INT_MIN;
int cntc2=0;
int res=0;
for(int i=0;i<n;i++){
char a=s[i];
if(a==c1){
cntc2--;
cntc1=cntc2;
cntc2=max(cntc2,0);
}
// 遇到了一个最大字符
else if(a==c2){
cntc2++;
cntc1++;
}
// 每次比较的都是当前序列之前两者的差,如果没有遇到b
// cntc1一直都是小于0,如果遇到的b大于a,此值依然是小于0
// 例如:abbaa
// cntc1中记录的是为下一次遇到b准备的值
//例如,abbaaab,到第三个b,前边的最大差数目为3
// aabaaab,前边最大差数目为4
res=max(res,cntc1);
}
return res;
}
int largestVariance(string s) {
int res=0;
unordered_set<char> se;
for(auto a : s){
se.insert(a);
}
// 枚举最大最小字符
for(auto a : se){
for(auto b : se){
if(a==b)
continue;
res=max(check(a,b,s),res);
}
}
return res;
}
};