替换后的最长重复字符串

200 阅读2分钟

题目

给你一个仅由大写英文字母组成的字符串,你可以将任意位置上的字符替换成另外的字符,总共可最多替换 k 次。在执行上述操作后,找到包含重复字母的最长子串的长度。

注意:字符串长度 和 k 不会超过 104。

 

示例 1:

输入:s = "ABAB", k = 2 输出:4 解释:用两个'A'替换为两个'B',反之亦然。

滑动窗口


public class Main {


    public static void main(String[] args) {

        Main main = new Main();
        main.characterReplacement("AABABBA", 1);

    }
    public int characterReplacement(String s, int k) {
        // charAppearTimes记录在滑动窗口内不同字符出现的次数
        int [] charAppearTimes = new int [26];
        // 需要保存滑动窗口内 出现过的某个字母的历史最大值
        int windowMaxTimes = 0;
        int left = 0;
        int right = 0;
        while (right < s.length()) {
            char temp = s.charAt(right);
            // A的ASCII码是65, 减去A是将所有的大写字符平移到0-26
            charAppearTimes[temp - 'A'] += 1;
            windowMaxTimes = Math.max(charAppearTimes[temp - 'A'], windowMaxTimes);
            // 如果windowMaxTimes + k > right - left + 1 就说明窗口可以尝试扩大
            if (windowMaxTimes + k >= right - left + 1) {
                right++;
                continue;
            }
            // 窗口长度不变, 进行滑动, 移除滑出去的元素, 左右指针均+1
            charAppearTimes[s.charAt(left) - 'A'] -= 1;
            left ++;
            right++;
        }

        return right - left;


    }

}

基本思路

  1. 题目可以理解为在一个长度为l的窗口内, 如果该窗口内的重复字母为n个, 那么如果n + k >= l, 就说明该窗口的长度就是这段字符串替换后的最长重复字符串, 因此可以尝试扩大窗口, 继续判断是否符合n + k >= l的条件.

  2. 用一个26长度的数字来记录窗口内每种字符出现的次数, 注意需要对ASCII码进行偏移, 例如charAppearTimes[s.charAt(right) - 'A']这种写法

  3. 采用左右指针的方式, 如果需要扩大窗口, 那么right++, 然后增加新添加字符的次数

  4. 如果是窗口滑动, 那么left ++ , right ++ , 同时需要移除窗口最左边的元素, 移入右边的元素, 完成相应次数的加减. charAppearTimes[s.charAt(left) - 'A'] -= 1;这个就没注意, 老写错