【力扣】424. 替换后的最长重复字符

以下为力扣题友思路,以及本人代码

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

  • 题目
  • 示例1
  • 示例2
  • 题友思路 滑动窗口
  • 本人代码
    • 复杂度分析

题目

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

示例1

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

示例2

输入:s = “AABABBA”, k = 1
输出:4
解释:将中间的一个’A’替换为’B’,字符串变为 “AABBBBA”。子串 “BBBB” 有最长重复字母, 答案为 4。

题友思路 滑动窗口

本题可以先退化成考虑 K = 0 的情况,此时题目就变成了求解字符串中最长连续子串问题。我们可以通过这个特例先了解以下滑动窗口的求解过程。
【力扣】424. 替换后的最长重复字符_第1张图片上图的求解过程展示中,窗口从左至右不断扩张/滑动,当窗口触达字符串末尾字符时,运算结束,窗口的宽度为最终结果。初始窗口的宽度为 1,我们不断的通过向当前窗口覆盖的子串后面追加一个字符看是否能满足我们的要求。如果满足,则窗口扩张;如果不满足,则窗口向右滑动。

当 K > 0 时,子串的条件变成了允许我们变换子串中的 K 个字符使其变成一个连续子串。那么这个题的关键点就是我们如何判断一个字符串改变 K 个字符,能够变成一个连续串。如果当前字符串中的出现次数最多的字母个数 + K 大于串长度,那么这个串就是满足条件的。

我们维护一个数组 int[26] 来存储当前窗口中各个字母的出现次数,left 表示窗口的左边界,right 表示窗口的右边界。

  • 窗口扩张:left 不变,right ++
  • 窗口滑动:left ++,right ++

historyMax 保存滑动窗口内相同字母出现次数的历史最大值,通过判断窗口宽度(right - left + 1)是否大于 historyMax + K 来决定窗口是否做滑动,否则窗口就扩张。

本人代码

class Solution {
    public int characterReplacement(String s, int k) {
        if (s == null)
            return 0;

        int[] map = new int[26];
        char[] c = s.toCharArray();
        int left = 0, historyMax = 0, right;
        for (right=0; right<c.length; right++)
        {
            int index = c[right]-'A';
            map[index] ++;
            historyMax = Math.max(historyMax, map[index]);
            if (right-left+1 > historyMax+k)
            {
                map[c[left]-'A'] --;
                left ++;
            }
        }
        return c.length-left;
    }
}

复杂度分析

  • 时间复杂度:O(n),其中 n 为字符串的长度。
  • 空间复杂度:O(1)。

题友思路出处如下
作者:migoo
链接:https://leetcode-cn.com/problems/longest-repeating-character-replacement/solution/tong-guo-ci-ti-liao-jie-yi-xia-shi-yao-shi-hua-don/
来源:力扣(LeetCode)

你可能感兴趣的:(力扣,leetcode,java)