424. 替换后的最长重复字符
Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
题目描述
给你一个字符串 s 和一个整数 k 。你可以选择字符串中的任一字符,并将其更改为任何其他大写英文字符。该操作最多可执行 k 次。
在执行上述操作后,返回包含相同字母的最长子字符串的长度。
示例 1:
输入: s = "ABAB", k = 2
输出: 4
解释: 用两个'A'替换为两个'B',反之亦然。
具体题目链接: 题目链接
思路:
思路:滑动窗口思路
窗口扩展时寻找可行解,窗口收缩时优化可行解
当滑动窗口可以定长时,一直维护k个长度的滑动窗口即可
当滑动窗口需要不定长时,需要通过特定条件(比如滑动窗口的总和)来判断left和right指针 到底是移动哪个
分析:
维护一个滑动窗口window的数组:
right一直可以++,window的值也是++;
当滑动窗口的长度right-left + 1 > typemax + k,left++一次(重点)
再比较大小
本质上滑动窗口是一种技巧,不需要hash表
细节:定义一些变量
hash表:维护t的字符的种类和具体的个数
typemax:最多字符种类的个数
// 右边界先移动找到一个满足题意的可以替换 k 个字符以后,所有字符都变成一样的当前看来最长的子串,直到右边界纳入一个字符以后,不能满足的时候停下;
// 然后考虑左边界向右移动,左边界只须要向右移动一格以后,右边界就又可以开始向右移动了,继续尝试找到更长的目标子串;每次left++只执行一次即可,循环的话while和if都是可以的
代码:
var characterReplacement = function(s, k) {
let n = s.length;
if(n<2)return n;
let window = new Array(26).fill(0);
let typemax = 0;
let left = 0;
let right = 0;
let res = 0;
while(right<n) {
window[s[right].charCodeAt() - 'A'.charCodeAt()]++;//维护window里面有几个s[right];
typemax = Math.max(typemax, window[s[right].charCodeAt() - 'A'.charCodeAt()]);
// 右边界先移动找到一个满足题意的可以替换 k 个字符以后,所有字符都变成一样的当前看来最长的子串,直到右边界纳入一个字符以后,不能满足的时候停下;
// 然后考虑左边界向右移动,左边界只须要向右移动一格以后,右边界就又可以开始向右移动了,继续尝试找到更长的目标子串;每次left++只执行一次即可,循环的话while和if都是可以的
while(right-left + 1 > typemax + k) {
window[s[left].charCodeAt() - 'A'.charCodeAt()]--;
left++;
}
// 替换后的最长重复子串就产生在右边界、左边界交替向右移动的过程中。
res = Math.max(res, right-left+1);
right++;
}
return res;
};
总结:
这是算法系列文章「滑动窗口」的相关题解
类型滑动窗口类型题目,解题方法窗口扩展时寻找可行解,窗口收缩时优化可行解