题目要求:小F得到了一个特殊的字符串,这个字符串只包含字符A、S、D、F,其长度总是4的倍数。他的任务是通过尽可能少的替换,使得A、S、D、F这四个字符在字符串中出现的频次相等。求出实现这一条件的最小子串长度。
问题理解
一个只包含字符 A、S、D、F 的字符串,且字符串的长度总是4的倍数。目标是使得这四个字符在字符串中出现的频次相等。为了实现这一目标,需要通过尽可能少的替换操作来达到这个条件。
数据结构选择
- 频次统计:首先,我们需要统计每个字符在字符串中出现的频次。
- 差值计算:然后,计算每个字符需要增加或减少的频次,以使得每个字符的频次达到目标频次(即字符串长度除以4)。
- 滑动窗口:使用滑动窗口技术来找到最小的子串,使得该子串中包含足够多的字符来满足差值要求。
算法步骤
-
初始化:
- 计算目标频次
targetFreq,即字符串长度除以4。 - 统计每个字符的当前频次。
- 计算每个字符需要增加或减少的频次
diff。
- 计算目标频次
-
滑动窗口:
- 使用两个指针
left和right来表示窗口的左右边界。 - 扩展窗口(移动
right),并更新窗口内每个字符的频次。 - 当窗口内的字符频次满足
diff要求时,记录当前窗口的长度,并尝试缩小窗口(移动left)。 - 继续上述过程,直到遍历完整个字符串。
- 使用两个指针
-
返回结果:
- 返回找到的最小窗口长度。
算法实现
public class Main {
public static int solution(String input) {
int n = input.length();
int targetFreq = n / 4; // 目标频次
// 统计当前频次
int[] freq = new int[4]; // 0: A, 1: S, 2: D, 3: F
for (char c : input.toCharArray()) {
freq[charToIndex(c)]++;
}
// 计算差值
int[] diff = new int[4];
for (int i = 0; i < 4; i++) {
diff[i] = Math.max(0, freq[i] - targetFreq);
}
// 如果所有字符的频次已经相等,直接返回0
if (diff[0] == 0 && diff[1] == 0 && diff[2] == 0 && diff[3] == 0) {
return 0;
}
// 滑动窗口
int left = 0, right = 0;
int minLen = n; // 初始化为最大可能值
int[] windowCount = new int[4];
while (right < n) {
// 扩展窗口
windowCount[charToIndex(input.charAt(right))]++;
right++;
// 检查窗口是否满足条件
while (isValidWindow(windowCount, diff)) {
minLen = Math.min(minLen, right - left);
// 缩小窗口
windowCount[charToIndex(input.charAt(left))]--;
left++;
}
}
return minLen;
}
// 将字符转换为索引
private static int charToIndex(char c) {
switch (c) {
case 'A': return 0;
case 'S': return 1;
case 'D': return 2;
case 'F': return 3;
default: throw new IllegalArgumentException("Invalid character: " + c);
}
}
// 检查窗口是否满足条件
private static boolean isValidWindow(int[] windowCount, int[] diff) {
for (int i = 0; i < 4; i++) {
if (windowCount[i] < diff[i]) {
return false;
}
}
return true;
}
public static void main(String[] args) {
// 你可以添加更多测试用例
System.out.println(solution("ADDF") == 1);
System.out.println(solution("ASAFASAFADDD") == 3);
}
}
关键点
- 频次统计:确保正确统计每个字符的频次。
- 差值计算:正确计算每个字符需要增加或减少的频次。
- 滑动窗口:确保窗口内的字符频次满足
diff要求,并找到最小的窗口长度。