题目分析
题目要求我们通过尽可能少的替换,使得给定字符串中的字符 A、S、D、F 出现的频次相等。字符串的长度总是 4 的倍数,因此每个字符的目标频次是字符串长度的四分之一。
我们需要找到一个最短的子串,通过替换该子串中的某些字符,使得整个字符串满足每个字符的频次相等。
解题思路
所以解题思路就比较清晰了,用滑动窗口做字符串替换。
- 统计字符频次:首先统计字符串中每个字符的出现频次。
- 确定需要替换的字符:找出哪些字符的频次超过目标频次,并计算需要替换的数量。
- 滑动窗口:使用滑动窗口技术找到包含所有需要替换字符的最小子串。
代码实现
def solution(input_str):
n = len(input_str)
count_target = n // 4
# 统计每个字符的频率
frequency = {}
for c in input_str:
if c in frequency:
frequency[c] += 1
else:
frequency[c] = 1
# 找出需要替换的字符以及需要替换的数量
required_changes = {}
for ch, count in frequency.items():
if count > count_target:
required_changes[ch] = count - count_target
# 如果不需要替换,直接返回 0
if not required_changes:
return 0
# 使用滑动窗口找到最小的子串
left, right = 0, 0
min_len = n + 1
window_count = {}
while right < n:
right_char = input_str[right]
if right_char in window_count:
window_count[right_char] += 1
else:
window_count[right_char] = 1
right += 1
# 检查当前窗口是否包含所有需要替换的字符
def window_contains_required_changes():
for ch, req_count in required_changes.items():
if window_count.get(ch, 0) < req_count:
return False
return True
while window_contains_required_changes():
min_len = min(min_len, right - left)
left_char = input_str[left]
if left_char in window_count:
window_count[left_char] -= 1
left += 1
return min_len
if __name__ == "__main__":
import sys
input_str = input().strip()
print(solution(input_str))
代码解释
-
统计字符频次:
count_target = n // 4计算每个字符的目标频次。frequency字典统计字符串中每个字符的出现频次。
-
确定需要替换的字符:
required_changes字典记录需要替换的字符及其超过目标频次的数量。- 如果
required_changes为空,说明字符串已经满足条件,直接返回 0。
-
滑动窗口:
- 初始化两个指针
left和right,用于表示滑动窗口的左右边界。 min_len用于记录最小子串的长度,初始值设为n + 1,表示一个不可能的值。window_count字典用于记录当前窗口中每个字符的频次。- 在
while right < n循环中,右指针right逐渐向右移动,扩展窗口。 window_contains_required_changes函数检查当前窗口是否包含所有需要替换的字符及其数量。- 如果当前窗口包含所有需要替换的字符,则左指针
left逐渐向右移动,缩小窗口,同时更新min_len。
- 初始化两个指针
测试样例
- 样例1:输入 "ADDF",输出 1。
- 字符频次:A(1), D(2), F(1)。
- 需要替换 D 一次。
- 最小子串长度为 1。
- 样例2:输入 "ASAFASAFADDD",输出 3。
- 字符频次:A(4), S(2), F(2), D(4)。
- 需要替换 D 一次。
- 最小子串长度为 3。
- 样例3:输入 "SSDDFFFFAAAS",输出 1。
- 字符频次:S(3), D(2), F(4), A(3)。
- 需要替换 F 一次。
- 最小子串长度为 1。
- 样例4:输入 "AAAASSSSDDDDFFFF",输出 0。
- 字符频次:A(4), S(4), D(4), F(4)。
- 已经满足条件,不需要替换。
- 样例5:输入 "AAAADDDDAAAASSSS",输出 4。
- 字符频次:A(6), D(4), S(4)。
- 需要替换 A 两次。
- 最小子串长度为 4。