Given a string that consists of only uppercase English letters, you can replace any letter in the string with another letter at most k times. Find the length of a longest substring containing all repeating letters you can get after performing the above operations.
Note:
Both the string's length and k will not exceed 104.
Example 1:
Input: s = "ABAB", k = 2 Output: 4 Explanation: Replace the two 'A's with two 'B's or vice versa.
Example 2:
Input: s = "AABABBA", k = 1 Output: 4 Explanation: Replace the one 'A' in the middle with 'B' and form "AABBBBA". The substring "BBBB" has the longest repeating letters, which is 4.
這道題給我們了一個字符串,說我們有k次隨意置換任意字符的機會,讓我們找出最長的重復字符的字符串。這道題跟之前那道 Longest Substring with At Most K Distinct Characters 很像,都需要用滑動窗口 Sliding Window 來解。我們首先來想,如果沒有k的限制,讓我們求把字符串變成只有一個字符重復的字符串需要的最小置換次數,那么就是字符串的總長度減去出現次數最多的字符的個數。如果加上k的限制,我們其實就是求滿足 (子字符串的長度減去出現次數最多的字符個數)<=k 的最大子字符串長度即可,搞清了這一點,我們也就應該知道怎么用滑動窗口來解了吧。我們用一個變量 start 記錄滑動窗口左邊界,初始化為0,然后遍歷字符串,每次累加出現字符的個數,然后更新出現最多字符的個數,然后我們判斷當前滑動窗口是否滿足之前說的那個條件,如果不滿足,我們就把滑動窗口左邊界向右移動一個,並注意去掉的字符要在 counts 里減一,直到滿足條件,我們更新結果 res 即可。需要注意的是,當滑動窗口的左邊界向右移動了后,窗口內的相同字母的最大個數貌似可能會改變啊,為啥這里不用更新 maxCnt 呢?這是個好問題,原因是此題讓求的是最長的重復子串,maxCnt 相當於卡了一個窗口大小,我們並不希望窗口變小,雖然窗口在滑動,但是之前是出現過跟窗口大小相同的符合題意的子串,縮小窗口沒有意義,並不會使結果 res 變大,所以我們才不更新 maxCnt 的,參見代碼如下:
class Solution { public: int characterReplacement(string s, int k) { int res = 0, maxCnt = 0, start = 0; vector<int> counts(26, 0); for (int i = 0; i < s.size(); ++i) { maxCnt = max(maxCnt, ++counts[s[i] - 'A']); while (i - start + 1 - maxCnt > k) { --counts[s[start] - 'A']; ++start; } res = max(res, i - start + 1); } return res; } };
類似題目:
Longest Substring with At Least K Repeating Characters
Longest Substring with At Most K Distinct Characters
Longest Substring with At Most Two Distinct Characters
Longest Substring Without Repeating Characters
參考資料:
https://leetcode.com/problems/longest-repeating-character-replacement/