【LeetCode】424. 替換後的最長重複字符

424. 替換後的最長重複字符

知識點:字符串,滑動窗口ui

題目描述

給你一個僅由大寫英文字母組成的字符串,你能夠將任意位置上的字符替換成另外的字符,總共可最多替換 k 次。在執行上述操做後,找到包含重複字母的最長子串的長度。code

注意:字符串長度 和 k 不會超過 104。leetcode

示例
輸入:s = "ABAB", k = 2
輸出:4
解釋:用兩個'A'替換爲兩個'B',反之亦然。

輸入:s = "AABABBA", k = 1
輸出:4
解釋:
將中間的一個'A'替換爲'B',字符串變爲 "AABBBBA"。
子串 "BBBB" 有最長重複字母, 答案爲 4。

解法一:滑動窗口

這道題其實挺複雜的,裏面有一些細節很難想;
想一下滑動窗口模板:
這道題目的條件時什麼:當前窗口裏出現次數最多的字母+k等於窗口長度
當達到這個條件後,若是下一個字符不是出現最多的字符,那左窗口就要移動了。
因此咱們須要一個變量來記錄當前窗口哪一個字母出現的最大次數字符串

class Solution {
    public int characterReplacement(String s, int k) {
        int[] num = new int[26];
        int n = s.length();
        int maxn = 0;
        int left = 0, right = 0;
        while (right < n) {
            int indexR = s.charAt(right) - 'A';
            num[indexR]++;
            //求窗口中曾出現某字母的最大次數
            //計算某字母出如今某窗口中的最大次數,窗口長度只能增大或者不變
            //這樣作的意義:咱們求的是最長,若是找不到更長的維持長度不變返回結果不受影響
            maxn = Math.max(maxn, num[indexR]);
            //若是選擇了maxn,那說明又多消耗了一個k;檢查一下k還夠不夠用了,不夠用的話總體移動,注意窗口大小是不變的。   
            //長度len=right-left+1,如下簡稱len
            //len>字母出現最大次數+替換數目,說明k不夠用了,這時候得把窗口向左移;
            //分析一下,替換數目是不變的=k,字母出現最大次數是可能變化的,所以,只有字母出現最大次數增長的狀況,len才能拿到最大值
            //left和right一塊兒移動,len不變的
            if (right - left + 1 - maxn > k) {
                //這裏要減的,由於left越過該點,會對最大值有影響
                num[s.charAt(left) - 'A']--;
                left++;
            }
            //走完這裏的時候,其實right會多走一步
            right++;
        }
        //由於right多走一步,結果爲(right-1)-left+1==right-left
        return right - left;
    }
}

細節:get

  • 1.num中存的是什麼:num中放的是當前窗口中各字母的長度,因此當咱們將左邊界移動的時候,要把左邊界那個移出去的元素次數-1;
  • 2.maxn這個變量:要注意maxn這個變量是在維持一個歷史窗口中的最大值。爲何維持一個歷史最大值,而不是當前窗口,從根本緣由就在於窗口是隻增不減的;若是遍歷到的right可以不消耗k,那就能夠right++,繼續窗口擴張;若是遍歷到的right更多的消耗了k,那就要看消耗後k還夠不夠用了,要是不夠用了,那把整個窗口進行滑動,這時的窗口大小不變;

好比一個子串k=2,而後有一段他的最大重複個數maxn是4,這時候他的長度是6,而後移動滑動窗口到另外一段,若是這一串的最大重複個數小於4,那必定不會獲得一個大於6的結果,因此記錄歷史最大值是能夠了。記住咱們找的是最長,若是找不到更長,那就維持不變就能夠了io

相關連接

替換後的最長重複字符模板

相關文章
相關標籤/搜索