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

183 阅读1分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

题目描述

给你一个字符串 s 和一个整数 k 。你可以选择字符串中的任一字符,并将其更改为任何其他大写英文字符。该操作最多可执行 k 次。

在执行上述操作后,返回包含相同字母的最长子字符串的长度。

示例 1:

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

示例 2:

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

提示:

  • 1 <= s.length <= 105
  • s 仅由大写英文字母组成
  • 0 <= k <= s.length

题解

1.滑动窗口

这道题 因为需要相同字母,所以可以通过滑动窗口来解决,一直向右进行遍历,下面是几个步骤点。

  • 由题目可知,只有大写的英文字母,所以创建两个26个字符的数组并填充0

  • 循环时,保证 右指针始终++ 操作

  • 这个滑动窗口的值,也就是最长子字符串的长度。

  • 只有 窗口宽度 > 最长子串,才会将左指针进行++操作

附图可更好理解

image.png

image.png

image.png

image.png

image.png

image.png

可以看到,因为right++,所以窗口只会变大或者不变,窗口大小是不会减少的,所以我们可以返回 n-left ,即为结果值

const characterReplacement = (s, k) => {
  let n = s.length
  let left = 0
  let right = 0
  let maxNum = 0
  let strMap = new Array(26).fill(0)
  const getIndex = (str) => str.charCodeAt() - 'A'.charCodeAt()

  while (right < n) {
    strMap[getIndex(s[right])]++
    maxNum = Math.max(maxNum, strMap[getIndex(s[right])])

    // 窗口宽度 > 最长子串
    if (right - left + 1 > maxNum + k) {
      // 窗口平移,先将左指针所在的值去掉一个,再将左指针向右移动一位
      strMap[getIndex(s[left])]--
      left++
    }
    right++
  }

  return n - left
}

总结

题目 9 :双指针中的 滑动窗口的应用,这道题思路很重要,多看多画理解更为透彻。