最小替换子串长度
要解决这个问题,我们需要使得字符串中的字符A、S、D、F的频率相等,而实现这一目标时所需替换的最小字串长度就是我们要求的。
1 分析:
- 假设输入字符串的长度为 n,那么每个字符 A、S、D、F 应该各自出现 n / 4 次。
- 我们的目标是通过尽可能少的替换,使得所有字符都出现 n / 4 次。
- 如果某些字符的频率超过 n / 4,我们需要用其他字符来替换超出的部分。
- 我们需要找到一个最短的子串,使得替换这个子串中的字符后,整个字符串中 A、S、D、F 的频率变得相等。
2 解题思路:
- 使用滑动窗口的方法来寻找满足条件的最小子串。
- 首先计算字符串中 A、S、D、F 的初始频率。
- 如果初始频率已经满足要求,则不需要替换,直接返回0。
- 否则,使用滑动窗口去寻找一个最短的子串,使得替换这个子串可以让 A、S、D、F 的频率达到 n / 4。
3 核心思想:
解题的核心思想是滑动窗口,当窗口内所有字符的频率都不超过n/4时,我们尝试缩小窗口,并更新最小子串长度。
逻辑如下:
1、初始化频率统计:首先统计整个字符串中A、S、D、F的频率。
2、判断平衡:如果字符的频率已经符合n/4的要求,那么返回0(即不需要替换)。
3、使用滑动窗口寻找最短子串:
- 左指针 left 和右指针 right 分别表示窗口的起始和结束位置。
- 遍历字符串,当右指针 right 向右移动时,我们减少 right 位置字符的频率。
- 当窗口内的字符频率都低于或等于
n/4时,说明此窗口中的字符可以通过替换来达到平衡。
例如字符串:
ASAFASAFADDD
(1)初始化频率统计:count[A]=5,count[S]=2,count[F]=2,count[D]=3,minLen初始化为n
(2)判断平衡:n/4是3,现在不满足平衡的条件
(3)使用滑动窗口寻找最短子串
- left=0,right=0,count[A]=4,count[S]=2,count[F]=2,count[D]=3,频率不都小于等于3,right++
- left=0,right=1,count[A]=4,count[S]=1,count[F]=2,count[D]=3,频率不都小于等于3,right++
- left=0,right=2,count[A]=3,count[S]=1,count[F]=2,count[D]=3,频率都小于等于3,minLen=min(minLen,right-left+1),minLen=3,count[A]++,left++,频率不都小于等于3,right++
- left=1,right=3,count[A]=4,count[S]=1,count[F]=1,count[D]=3,频率不都小于等于3,right++
- left=1,right=4,count[A]=3,count[S]=1,count[F]=1,count[D]=3,频率都小于等于3,minLen=min(minLen,right-left+1),minLen=3,count[S]++,left++,频率都小于等于3,minLen=min(minLen,right-left+1),minLen=3,count[A]++,left++,频率不都小于等于3,right++
- left=3,right=5,count[A]=4,count[S]=2,count[F]=1,count[D]=3,频率不都小于等于3,right++
- 以此递推,最终得到最小的minLen=3
代码:
#include <iostream>
#include <string>
#include <unordered_map>
#include <algorithm>
int solution(std::string input) {
int n = input.size();
int target = n / 4;
std::unordered_map<char, int> count;
// 统计 A, S, D, F 的频率
for (char c : input) {
count[c]++;
}
// 检查是否已经符合要求
if (count['A'] == target && count['S'] == target && count['D'] == target && count['F'] == target) {
return 0;
}
// 滑动窗口寻找最小的子串
int min_length = n;
int left = 0;
for (int right = 0; right < n; ++right) {
count[input[right]]--;
// 检查当前窗口是否满足要求
while (count['A'] <= target && count['S'] <= target && count['D'] <= target && count['F'] <= target) {
min_length = std::min(min_length, right - left + 1);
count[input[left]]++;
left++;
}
}
return min_length;
}
int main() {
// You can add more test cases here
std::cout << (solution("ADDF") == 1) << std::endl;
std::cout << (solution("ASAFASAFADDD") == 3) << std::endl;
return 0;
}