类型:滑动窗口类型
问题
给你一个仅由大写英文字母组成的字符串,你可以将任意位置上的字符替换成另外的字符,总共可最多替换 k 次。在执行上述操作后,找到包含重复字母的最长子串的长度。
注意:字符串长度 和 k 不会超过 104。
示例 1:
输入:s = “ABAB”, k = 2
输出:4
解释:用两个’A’替换为两个’B’,反之亦然。
示例 2:
输入:s = “ABAA”, k = 0
输出:2
思路
左右双指针思想:
示例:s = AABCABBB,k = 2, 输出结果为6
从左边开始:A A B C A B B B ;初始左右指针都在索引0位
右指针移动:
右指针先动,右移一个,得到长度为1的子串“A”
继续右移一个,得到长度为2的子串“AA”
接着右移,得到长度为3的子串“AAB”,依然是合法的,因为K值为2,所以得到的子串中可以转变的字符长度只要小于k值,就可以一直右移;
什么时候不能右移了?
接着右移,得到长度为4的子串“AABC”
右移,长度为5的子串“AABCA”
右移,长度为6的子串“AABCAB”,是不合法的,此时需要移动左边的指针往右移;
左指针移动:
因为长度为6的子串“AABCAB”中有3个A,两个B,一个C,超过了k值;所以左、右指针往右移
移动一位,得到长度为6的子串“ABCABB”,依然不合法;
左指针移动,得到长度为5的子串“BCABB”,合法;
接下来右指针接着挪,得到长度为6的子串“BCABBB”,合法。遍历完成
代码
def characterReplacement(s: str, k: int) -> int:
res = 1
length = len(s)
if k >= length or length <= 1:
return length
# 可以不定义temp,节省空间
temp = []
temp_dict = collections.defaultdict(int)
for i in range(length):
temp.append(s[i])
temp_dict[s[i]] += 1
max_val = max(temp_dict.values())
# 此处就是左指针挪动的条件
while max_val + k < len(temp):
temp_dict[temp[0]] -= 1
temp = temp[1:]
max_val = max(temp_dict.values())
res = max(res, len(temp))
return res