424. 替换后的最长重复字符

124 阅读2分钟

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;
};

总结:

这是算法系列文章「滑动窗口」的相关题解

类型滑动窗口类型题目,解题方法窗口扩展时寻找可行解,窗口收缩时优化可行解