LeetCode424. 替换后的最长重复字符(双指针:滑动窗口)

1、题目描述

https://leetcode-cn.com/problems/longest-repeating-character-replacement/

给你一个仅由大写英文字母组成的字符串,你可以将任意位置上的字符替换成另外的字符,总共可最多替换 k 次。

在执行上述操作后,找到包含重复字母的最长子串的长度。

注意:字符串长度 和 k 不会超过 10^4。

输入:s = "ABAB", k = 2
输出:4
解释:用两个'A'替换为两个'B',反之亦然。
输入:s = "AABCABBB", k = 2
输出:6
解释:
将中间的一个'CA'替换为'BB',字符串变为 "AABBBBBB"。
子串 "BBBBBB" 有最长重复字母, 答案为 6。

 2、代码详解

双指针(滑动窗口)

  • 右边界先移动找到一个满足题意的可以替换 k 个字符以后,所有字符都变成一样的当前看来最长的子串,直到右边界纳入一个字符以后,不能满足的时候停下;
  • 然后考虑左边界向右移动,左边界只须要向右移动一格以后,右边界就又可以开始向右移动了,继续尝试找到更长的目标子串;
  • 替换后的最长重复子串就产生在右边界、左边界交替向右移动的过程中。

开区间写法:[left, right), 结果是right - left

class Solution(object):
    def characterReplacement(self, s, k):
        """
        :type s: str
        :type k: int
        :rtype: int
        """
        n = len(s)
        if n < 2:
            return n
        freq = [0] * 26  # 组维护每一个字符的出现次数,记录当前窗口字母出现的个数

        max_count = 0  # 记录字符出现次数最多那个字符 的次数
        res = 0
        left = 0
        right = 0

        # [left, right) 内最多替换 k 个字符可以得到只有一种字符的子串
        # 注意是开区间写法:right - left!!
        while right < n:
            freq[ord(s[right]) - ord('A')] += 1
            # print('滑动右边界:', freq)
            # 维护 maxCount,因为每一次右边界读入一个字符,字符频数增加,才会使得 maxCount 增加
            max_count = max(max_count, freq[ord(s[right]) - ord('A')])  # 比较之前记录的最大数 和 当前字符的数量
            right += 1  # !!
            if right - left - max_count > k:  # 若当前窗口大小 减去 窗口中最多相同字符的个数 大于 k 时,该区间内非最长重复字符超过了 k 个
                # 把其它不是最多出现的字符替换以后,都不能填满这个滑动的窗口,这个时候须要考虑左边界向右移动
                # 移出滑动窗口的时候,频数数组须要相应地做减法
                freq[ord(s[left]) - ord('A')] -= 1  # 将窗口最左边的字符 在计数数组中减1
                # print('滑动左边界:', freq)
                left += 1
            res = max(res, right - left)
        return res

https://leetcode-cn.com/problems/longest-repeating-character-replacement/solution/ti-huan-hou-de-zui-chang-zhong-fu-zi-fu-eaacp/

闭区间写法[left, right], 结果是right - left + 1

class Solution(object):
    def characterReplacement(self, s, k):
        """
        :type s: str
        :type k: int
        :rtype: int
        """
        n = len(s)
        if n < 2:
            return n
        freq = [0] * 26  # 组维护每一个字符的出现次数,记录当前窗口字母出现的个数

        max_count = 0  # 记录字符出现次数最多那个字符 的次数
        res = 0
        left = 0
        right = 0

        # [left, right]最多替换 k 个字符可以得到只有一种字符的子串
        # 注意是闭区间写法:right - left + 1 !!
        while right < n:
            freq[ord(s[right]) - ord('A')] += 1
            # print('滑动右边界:', freq)
            # 维护 maxCount,因为每一次右边界读入一个字符,字符频数增加,才会使得 maxCount 增加
            max_count = max(max_count, freq[ord(s[right]) - ord('A')])  # 比较之前记录的最大数 和 当前字符的数量

            if right - left + 1 - max_count > k:  # 若当前窗口大小 减去 窗口中最多相同字符的个数 大于 k 时,该区间内非最长重复字符超过了 k 个
                # 把其它不是最多出现的字符替换以后,都不能填满这个滑动的窗口,这个时候须要考虑左边界向右移动
                # 移出滑动窗口的时候,频数数组须要相应地做减法
                freq[ord(s[left]) - ord('A')] -= 1  # 将窗口最左边的字符 在计数数组中减1
                # print('滑动左边界:', freq)
                left += 1
            res = max(res, right - left + 1)
            right += 1  # !!
        return res

https://leetcode-cn.com/problems/longest-repeating-character-replacement/solution/fen-xiang-zhen-cang-de-shuang-zhi-zhen-m-fdsk/

  • 时间:O(N), N 是输入字符串 S 的长度
  • 空间:O(A), A 是输入字符串 S 出现的字符 ASCII 值的范围
上一篇:Pointproofs: Aggregating Proofs for Multiple Vector Commitments 学习笔记


下一篇:Excel-满足指定条件并且包含数字的单元格数目,DCOUNT()