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 <= 105s仅由大写英文字母组成0 <= k <= s.length
题解
1.滑动窗口
这道题 因为需要相同字母,所以可以通过滑动窗口来解决,一直向右进行遍历,下面是几个步骤点。
-
由题目可知,只有大写的英文字母,所以创建两个26个字符的数组并填充0
-
循环时,保证 右指针始终++ 操作
-
这个滑动窗口的值,也就是最长子字符串的长度。
-
只有 窗口宽度 > 最长子串,才会将左指针进行++操作
附图可更好理解
可以看到,因为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 :双指针中的 滑动窗口的应用,这道题思路很重要,多看多画理解更为透彻。