1. 程式人生 > >Leetcode 424.替換後的最長重複字元

Leetcode 424.替換後的最長重複字元

替換後的最長重複字元

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

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

示例 1:

輸入:

s = "ABAB", k = 2

 

輸出:

4

 

解釋:

用兩個'A'替換為兩個'B',反之亦然。

示例 2:

輸入:

s = "AABABBA", k = 1

 

輸出:

4

 

解釋:

將中間的一個'A'替換為'B',字串變為 "AABBBBA"。

子串 "BBBB" 有最長重複字母, 答案為 4。

 

 

思路:

 

題目的意思比較清楚,不過可能的情況有很多,不可能用程式碼去尋找最佳的替換位置,所以這裡採用一種滑動視窗的方法。

 

定義start和end兩個標記,中間的內容即是視窗,計算視窗內所有字母出現的次數,因為全是大寫字母,所以可以用一個26位的陣列來記錄視窗內每個字母出現的次數。

 

找到視窗內出現最多的次數,加上允許替換的字母數k,看是否超過視窗寬度,如果超過了,說明視窗還可以更長, 也就是說視窗內重複的字母的長度可以更長,就將end右移一位,形成新的視窗,然後繼續重複上面的步驟。如果沒超過,說明能構成的最長的重複字母長度已經到頂了,這時應該將start右移一位,來尋找新的可能的更長重複字母長度。

 

每次計算重複字母長度時,當出現更長的可能時,都更新最終的結果。

 

為了減少時間複雜度,我們不去每次都遍歷視窗來計算出現的字母次數,而是在移動end或者start時,將對應位置的字母的次數加一或者減一。

 

要注意各種邊界條件是什麼。

 

 1 public class Solution {
 2     public int characterReplacement(String s, int k) {
 3         if (s.length() < 1) return 0;
 4         int
start = 0; 5 int end = 0; 6 int res = 0; 7 int[] charNum = new int[26]; 8 charNum[s.charAt(0) - 'A']++; 9 while (s.length() > end) { 10 int maxChar = 0; 11 for (int i = 0; i < 26; i++) { 12 if (charNum[i] > maxChar) 13 maxChar = charNum[i]; 14 } 15 if (maxChar + k > end - start) { 16 end++; 17 if (end < s.length()) 18 charNum[s.charAt(end) - 'A']++; 19 } else { 20 charNum[s.charAt(start) - 'A']--; 21 start++; 22 } 23 if (maxChar + k > res) 24 res = maxChar + k <= s.length() ? maxChar + k : s.length(); 25 } 26 return res; 27 } 28 }