问题描述
小F得到了一个特殊的字符串,该字符串只包含字符 'A'、'S'、'D'、'F',且其长度总是4的倍数。任务是通过尽可能少的替换操作,使得 'A'、'S'、'D'、'F' 这四个字符在字符串中出现的频次相等。需要求出实现这一条件的最小子串长度。
样例分析
-
样例1:
input = "ADDF"- 目标频次:每个字符出现1次。
- 最小子串长度:1(将 'D' 替换为 'S')。
-
样例2:
input = "ASAFASAFADDD"- 目标频次:每个字符出现3次。
- 最小子串长度:3(将 "DDD" 替换为 "SSF" 或其他组合)。
-
样例3:
input = "SSDDFFFFAAAS"- 目标频次:每个字符出现3次。
- 最小子串长度:1(将 'S' 替换为 'A')。
-
样例4:
input = "AAAASSSSDDDDFFFF"- 目标频次:每个字符出现4次。
- 最小子串长度:0(已经满足条件)。
-
样例5:
input = "AAAADDDDAAAASSSS"- 目标频次:每个字符出现4次。
- 最小子串长度:4(将 "AAAA" 替换为 "SDFD" 或其他组合)。
解题步骤
步骤1:统计字符频次
- 统计整个字符串中每个字符的出现次数。
- 计算每个字符的目标频次
target_count,即n // 4。
步骤2:检查是否已满足条件
- 如果所有字符的出现次数都等于目标频次,则直接返回0。
步骤3:滑动窗口法
- 使用滑动窗口法来寻找最小子串长度。
- 初始化左边界
left和最小长度min_length。 - 遍历字符串,使用右边界
right来扩展窗口。 - 更新窗口内字符的频次。
- 检查当前窗口是否满足条件(即所有字符的频次都不超过目标频次)。
- 如果满足条件,更新最小长度,并移动左边界以缩小窗口。
代码实现
def solution(input):
n = len(input)
target_count = n // 4 # 每个字符的目标频次
# 统计整个字符串中每个字符的出现次数
count = {'A': 0, 'S': 0, 'D': 0, 'F': 0}
for char in input:
count[char] += 1
# 如果已经满足条件,直接返回0
if all(count[char] == target_count for char in 'ASDF'):
return 0
# 滑动窗口初始化
left = 0
min_length = n # 初始化最小长度为整个字符串的长度
# 滑动窗口右边界
for right in range(n):
# 更新窗口内字符频次
count[input[right]] -= 1
# 检查当前窗口是否满足条件
while all(count[char] <= target_count for char in 'ASDF'):
min_length = min(min_length, right - left + 1)
# 移动左边界
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)
测试用例
-
样例1:
input = "ADDF"- 输出:1
-
样例2:
input = "ASAFASAFADDD"- 输出:3
-
样例3:
input = "SSDDFFFFAAAS"- 输出:1
-
样例4:
input = "AAAASSSSDDDDFFFF"- 输出:0
-
样例5:
input = "AAAADDDDAAAASSSS"- 输出:4
总结
时间复杂度
- 该算法的时间复杂度为 𝑂(𝑛),其中 𝑛 是字符串的长度。这是因为我们使用了滑动窗口法,每个字符最多被处理两次(一次作为右边界,一次作为左边界)。
空间复杂度
- 该算法的空间复杂度为 𝑂(1),因为我们只使用了常数级的额外空间来存储字符频次和一些临时变量。
关键点
- 字符频次统计:首先统计每个字符的初始频次。
- 目标频次计算:计算每个字符的目标频次。
- 滑动窗口法:使用滑动窗口法来找到最小子串长度。
- 频次更新:在滑动窗口过程中,实时更新窗口内字符的频次。
- 条件检查:检查当前窗口是否满足条件,即所有字符的频次都不超过目标频次。