题目描述
给你一个字符串 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
解法
方法一:双指针
我们使用一个哈希表 cnt
统计字符串中每个字符出现的次数,使用双指针 l
和 r
维护一个滑动窗口,使得窗口的大小减去出现次数最多的字符的次数,结果不超过 $k$。
我们遍历字符串,每次更新窗口的右边界 r
,并更新窗口内的字符出现次数,同时更新出现过的字符的最大出现次数 mx
。当窗口的大小减去 mx
大于 $k$ 时,我们需要缩小窗口的左边界 l
,同时更新窗口内的字符出现次数,直到窗口的大小减去 mx
不大于 $k$。
最后,答案为 $n - l$,其中 $n$ 为字符串的长度。
时间复杂度 $O(n)$,空间复杂度 $O(|\Sigma|)$。其中 $n$ 为字符串的长度,而 $|\Sigma|$ 为字符集的大小,本题中字符集为大写英文字母,所以 $|\Sigma| = 26$。
| class Solution:
def characterReplacement(self, s: str, k: int) -> int:
cnt = Counter()
l = mx = 0
for r, c in enumerate(s):
cnt[c] += 1
mx = max(mx, cnt[c])
if r - l + 1 - mx > k:
cnt[s[l]] -= 1
l += 1
return len(s) - l
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14 | class Solution {
public int characterReplacement(String s, int k) {
int[] cnt = new int[26];
int l = 0, mx = 0;
int n = s.length();
for (int r = 0; r < n; ++r) {
mx = Math.max(mx, ++cnt[s.charAt(r) - 'A']);
if (r - l + 1 - mx > k) {
--cnt[s.charAt(l++) - 'A'];
}
}
return n - l;
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 | class Solution {
public:
int characterReplacement(string s, int k) {
int cnt[26]{};
int l = 0, mx = 0;
int n = s.length();
for (int r = 0; r < n; ++r) {
mx = max(mx, ++cnt[s[r] - 'A']);
if (r - l + 1 - mx > k) {
--cnt[s[l++] - 'A'];
}
}
return n - l;
}
};
|
1
2
3
4
5
6
7
8
9
10
11
12
13 | func characterReplacement(s string, k int) int {
cnt := [26]int{}
l, mx := 0, 0
for r, c := range s {
cnt[c-'A']++
mx = max(mx, cnt[c-'A'])
if r-l+1-mx > k {
cnt[s[l]-'A']--
l++
}
}
return len(s) - l
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13 | function characterReplacement(s: string, k: number): number {
const idx = (c: string) => c.charCodeAt(0) - 65;
const cnt: number[] = Array(26).fill(0);
const n = s.length;
let [l, mx] = [0, 0];
for (let r = 0; r < n; ++r) {
mx = Math.max(mx, ++cnt[idx(s[r])]);
if (r - l + 1 - mx > k) {
--cnt[idx(s[l++])];
}
}
return n - l;
}
|