问题描述
小F得到了一个特殊的字符串,这个字符串只包含字符A、S、D、F,其长度总是4的倍数。他的任务是通过尽可能少的替换,使得A、S、D、F这四个字符在字符串中出现的频次相等。求出实现这一条件的最小子串长度。
测试样例
样例1:
输入:
input = "ADDF"
输出:1
样例2:
输入:
input = "ASAFASAFADDD"
输出:3
样例3:
输入:
input = "SSDDFFFFAAAS"
输出:1
样例4:
输入:
input = "AAAASSSSDDDDFFFF"
输出:0
样例5:
输入:
input = "AAAADDDDAAAASSSS"
输出:4
解题思路
- 计算目标频次:由于字符串长度是4的倍数,目标频次是字符串长度除以4。
- 统计当前频次:统计字符串中每个字符
A、S、D、F的当前频次。 - 计算差值:计算每个字符需要增加或减少的频次,使得每个字符的频次达到目标频次。
- 滑动窗口:使用滑动窗口技术来找到一个最小的子串,使得通过替换这个子串中的字符,可以满足所有字符的频次要求。
n = len(input)
target_freq = n // 4 # 目标频次
# 统计当前频次
current_freq = {'A': 0, 'S': 0, 'D': 0, 'F': 0}
for char in input:
current_freq[char] += 1
# 计算每个字符需要增加或减少的频次
needed_changes = {char: max(0, current_freq[char] - target_freq) for char in 'ASDF'}
# 如果所有字符的频次已经相等,直接返回0
if sum(needed_changes.values()) == 0:
return 0
# 使用滑动窗口找到最小的子串
left = 0
min_length = n # 初始化为最大可能值
window_count = {'A': 0, 'S': 0, 'D': 0, 'F': 0}
for right in range(n):
window_count[input[right]] += 1
# 检查当前窗口是否满足所有字符的频次要求
while all(window_count[char] >= needed_changes[char] for char in 'ASDF'):
min_length = min(min_length, right - left + 1)
window_count[input[left]] -= 1
left += 1
return min_length
if __name__ == "__main__":
# You can add more test cases here
print(solution("ADDF") == 1)
print(solution("ASAFASAFADDD") == 3)
关键步骤解释
- 统计当前频次:使用字典
current_freq来记录每个字符的当前频次。 - 计算差值:使用字典
needed_changes来记录每个字符需要增加或减少的频次。 - 滑动窗口:使用两个指针
left和right来表示当前窗口的边界,window_count记录当前窗口内每个字符的频次。通过移动right指针扩展窗口,移动left指针缩小窗口,直到找到满足条件的最小子串。
心得体会
1. 问题分解与模块化
代码首先将问题分解为几个关键步骤:计算目标频次、统计当前频次、计算差值、以及使用滑动窗口找到最小子串。这种模块化的设计使得代码结构清晰,易于理解和维护。
2. 字典的使用
字典在代码中被广泛使用,用于统计字符的频次和记录需要的变化量。字典的键值对结构非常适合这种需要快速查找和更新的场景。
3. 滑动窗口技术
滑动窗口技术是解决这类问题的有效方法。通过维护一个窗口,可以在O(n)的时间复杂度内找到满足条件的最小子串。滑动窗口的核心在于动态调整窗口的边界,以确保窗口内的字符频次满足要求。
4. 边界条件的处理
代码中对边界条件进行了细致的处理。例如,当所有字符的频次已经相等时,直接返回0,避免了不必要的计算。这种对边界条件的处理可以提高代码的效率和鲁棒性。
5. 代码的可读性和可维护性
代码的注释和变量命名都很清晰,有助于理解代码的逻辑。良好的代码风格和注释习惯可以提高代码的可读性和可维护性。
6. 测试用例的重要性
代码末尾提供了测试用例,这有助于验证代码的正确性。通过添加更多的测试用例,可以覆盖更多的边界情况,确保代码的健壮性。
7. 时间复杂度分析
代码的时间复杂度为O(n),其中n是字符串的长度。滑动窗口的每次操作都是线性的,因此整体的时间复杂度是可接受的。
8. 空间复杂度分析
代码的空间复杂度为O(1),因为使用了固定大小的字典来存储频次信息,不随输入规模增大而增加。