From 72f6492dab4011ae9c7307e53a5786fba6ce37b2 Mon Sep 17 00:00:00 2001 From: yanglbme Date: Tue, 4 Jun 2024 18:55:28 +0800 Subject: [PATCH] feat: add solutions to lc problem: No.424 No.0424.Longest Repeating Character Replacement --- .../README.md | 105 ++++++++++-------- .../README_EN.md | 105 ++++++++++-------- .../Solution.cpp | 18 ++- .../Solution.go | 21 ++-- .../Solution.java | 19 ++-- .../Solution.py | 19 ++-- .../Solution.ts | 13 +++ 7 files changed, 169 insertions(+), 131 deletions(-) create mode 100644 solution/0400-0499/0424.Longest Repeating Character Replacement/Solution.ts diff --git a/solution/0400-0499/0424.Longest Repeating Character Replacement/README.md b/solution/0400-0499/0424.Longest Repeating Character Replacement/README.md index d5091aad4c8ac..cedb62db4d5a0 100644 --- a/solution/0400-0499/0424.Longest Repeating Character Replacement/README.md +++ b/solution/0400-0499/0424.Longest Repeating Character Replacement/README.md @@ -59,7 +59,15 @@ tags: -### 方法一 +### 方法一:双指针 + +我们使用一个哈希表 `cnt` 统计字符串中每个字符出现的次数,使用双指针 `l` 和 `r` 维护一个滑动窗口,使得窗口的大小减去出现次数最多的字符的次数,结果不超过 $k$。 + +我们遍历字符串,每次更新窗口的右边界 `r`,并更新窗口内的字符出现次数,同时更新出现过的字符的最大出现次数 `mx`。当窗口的大小减去 `mx` 大于 $k$ 时,我们需要缩小窗口的左边界 `l`,同时更新窗口内的字符出现次数,直到窗口的大小减去 `mx` 不大于 $k$。 + +最后,答案为 $n - l$,其中 $n$ 为字符串的长度。 + +时间复杂度 $O(n)$,空间复杂度 $O(|\Sigma|)$。其中 $n$ 为字符串的长度,而 $|\Sigma|$ 为字符集的大小,本题中字符集为大写英文字母,所以 $|\Sigma| = 26$。 @@ -68,16 +76,15 @@ tags: ```python class Solution: def characterReplacement(self, s: str, k: int) -> int: - counter = [0] * 26 - i = j = maxCnt = 0 - while i < len(s): - counter[ord(s[i]) - ord('A')] += 1 - maxCnt = max(maxCnt, counter[ord(s[i]) - ord('A')]) - if i - j + 1 > maxCnt + k: - counter[ord(s[j]) - ord('A')] -= 1 - j += 1 - i += 1 - return i - j + 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 ``` #### Java @@ -85,19 +92,16 @@ class Solution: ```java class Solution { public int characterReplacement(String s, int k) { - int[] counter = new int[26]; - int i = 0; - int j = 0; - for (int maxCnt = 0; i < s.length(); ++i) { - char c = s.charAt(i); - ++counter[c - 'A']; - maxCnt = Math.max(maxCnt, counter[c - 'A']); - if (i - j + 1 - maxCnt > k) { - --counter[s.charAt(j) - 'A']; - ++j; + 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 i - j; + return n - l; } } ``` @@ -108,18 +112,16 @@ class Solution { class Solution { public: int characterReplacement(string s, int k) { - vector counter(26); - int i = 0, j = 0, maxCnt = 0; - for (char& c : s) { - ++counter[c - 'A']; - maxCnt = max(maxCnt, counter[c - 'A']); - if (i - j + 1 > maxCnt + k) { - --counter[s[j] - 'A']; - ++j; + 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']; } - ++i; } - return i - j; + return n - l; } }; ``` @@ -128,20 +130,35 @@ public: ```go func characterReplacement(s string, k int) int { - counter := make([]int, 26) - j, maxCnt := 0, 0 - for i := range s { - c := s[i] - 'A' - counter[c]++ - if maxCnt < counter[c] { - maxCnt = counter[c] - } - if i-j+1 > maxCnt+k { - counter[s[j]-'A']-- - j++ + 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) - j + return len(s) - l +} +``` + +#### TypeScript + +```ts +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; } ``` diff --git a/solution/0400-0499/0424.Longest Repeating Character Replacement/README_EN.md b/solution/0400-0499/0424.Longest Repeating Character Replacement/README_EN.md index b2a55c131b57d..bc250f424901f 100644 --- a/solution/0400-0499/0424.Longest Repeating Character Replacement/README_EN.md +++ b/solution/0400-0499/0424.Longest Repeating Character Replacement/README_EN.md @@ -55,7 +55,15 @@ There may exists other ways to achieve this answer too. -### Solution 1 +### Solution 1: Two Pointers + +We use a hash table `cnt` to count the occurrence of each character in the string, and two pointers `l` and `r` to maintain a sliding window, such that the size of the window minus the count of the most frequent character does not exceed $k$. + +We iterate through the string, updating the right boundary `r` of the window each time, updating the count of characters within the window, and updating the maximum count `mx` of the characters that have appeared. When the size of the window minus `mx` is greater than $k$, we need to shrink the left boundary `l` of the window, updating the count of characters within the window, until the size of the window minus `mx` is no longer greater than $k$. + +Finally, the answer is $n - l$, where $n$ is the length of the string. + +The time complexity is $O(n)$, and the space complexity is $O(|\Sigma|)$. Where $n$ is the length of the string, and $|\Sigma|$ is the size of the character set. In this problem, the character set is uppercase English letters, so $|\Sigma| = 26$. @@ -64,16 +72,15 @@ There may exists other ways to achieve this answer too. ```python class Solution: def characterReplacement(self, s: str, k: int) -> int: - counter = [0] * 26 - i = j = maxCnt = 0 - while i < len(s): - counter[ord(s[i]) - ord('A')] += 1 - maxCnt = max(maxCnt, counter[ord(s[i]) - ord('A')]) - if i - j + 1 > maxCnt + k: - counter[ord(s[j]) - ord('A')] -= 1 - j += 1 - i += 1 - return i - j + 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 ``` #### Java @@ -81,19 +88,16 @@ class Solution: ```java class Solution { public int characterReplacement(String s, int k) { - int[] counter = new int[26]; - int i = 0; - int j = 0; - for (int maxCnt = 0; i < s.length(); ++i) { - char c = s.charAt(i); - ++counter[c - 'A']; - maxCnt = Math.max(maxCnt, counter[c - 'A']); - if (i - j + 1 - maxCnt > k) { - --counter[s.charAt(j) - 'A']; - ++j; + 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 i - j; + return n - l; } } ``` @@ -104,18 +108,16 @@ class Solution { class Solution { public: int characterReplacement(string s, int k) { - vector counter(26); - int i = 0, j = 0, maxCnt = 0; - for (char& c : s) { - ++counter[c - 'A']; - maxCnt = max(maxCnt, counter[c - 'A']); - if (i - j + 1 > maxCnt + k) { - --counter[s[j] - 'A']; - ++j; + 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']; } - ++i; } - return i - j; + return n - l; } }; ``` @@ -124,20 +126,35 @@ public: ```go func characterReplacement(s string, k int) int { - counter := make([]int, 26) - j, maxCnt := 0, 0 - for i := range s { - c := s[i] - 'A' - counter[c]++ - if maxCnt < counter[c] { - maxCnt = counter[c] - } - if i-j+1 > maxCnt+k { - counter[s[j]-'A']-- - j++ + 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) - j + return len(s) - l +} +``` + +#### TypeScript + +```ts +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; } ``` diff --git a/solution/0400-0499/0424.Longest Repeating Character Replacement/Solution.cpp b/solution/0400-0499/0424.Longest Repeating Character Replacement/Solution.cpp index 0908d13a2a6c6..81e6c015c94b9 100644 --- a/solution/0400-0499/0424.Longest Repeating Character Replacement/Solution.cpp +++ b/solution/0400-0499/0424.Longest Repeating Character Replacement/Solution.cpp @@ -1,17 +1,15 @@ class Solution { public: int characterReplacement(string s, int k) { - vector counter(26); - int i = 0, j = 0, maxCnt = 0; - for (char& c : s) { - ++counter[c - 'A']; - maxCnt = max(maxCnt, counter[c - 'A']); - if (i - j + 1 > maxCnt + k) { - --counter[s[j] - 'A']; - ++j; + 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']; } - ++i; } - return i - j; + return n - l; } }; \ No newline at end of file diff --git a/solution/0400-0499/0424.Longest Repeating Character Replacement/Solution.go b/solution/0400-0499/0424.Longest Repeating Character Replacement/Solution.go index 4faa63c2a3cda..491cdc8978872 100644 --- a/solution/0400-0499/0424.Longest Repeating Character Replacement/Solution.go +++ b/solution/0400-0499/0424.Longest Repeating Character Replacement/Solution.go @@ -1,16 +1,13 @@ func characterReplacement(s string, k int) int { - counter := make([]int, 26) - j, maxCnt := 0, 0 - for i := range s { - c := s[i] - 'A' - counter[c]++ - if maxCnt < counter[c] { - maxCnt = counter[c] - } - if i-j+1 > maxCnt+k { - counter[s[j]-'A']-- - j++ + 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) - j + return len(s) - l } \ No newline at end of file diff --git a/solution/0400-0499/0424.Longest Repeating Character Replacement/Solution.java b/solution/0400-0499/0424.Longest Repeating Character Replacement/Solution.java index f2153f14bffd2..48b6d19a521b8 100644 --- a/solution/0400-0499/0424.Longest Repeating Character Replacement/Solution.java +++ b/solution/0400-0499/0424.Longest Repeating Character Replacement/Solution.java @@ -1,17 +1,14 @@ class Solution { public int characterReplacement(String s, int k) { - int[] counter = new int[26]; - int i = 0; - int j = 0; - for (int maxCnt = 0; i < s.length(); ++i) { - char c = s.charAt(i); - ++counter[c - 'A']; - maxCnt = Math.max(maxCnt, counter[c - 'A']); - if (i - j + 1 - maxCnt > k) { - --counter[s.charAt(j) - 'A']; - ++j; + 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 i - j; + return n - l; } } \ No newline at end of file diff --git a/solution/0400-0499/0424.Longest Repeating Character Replacement/Solution.py b/solution/0400-0499/0424.Longest Repeating Character Replacement/Solution.py index 1bd364b3e0a14..09d21f021fa6a 100644 --- a/solution/0400-0499/0424.Longest Repeating Character Replacement/Solution.py +++ b/solution/0400-0499/0424.Longest Repeating Character Replacement/Solution.py @@ -1,12 +1,11 @@ class Solution: def characterReplacement(self, s: str, k: int) -> int: - counter = [0] * 26 - i = j = maxCnt = 0 - while i < len(s): - counter[ord(s[i]) - ord('A')] += 1 - maxCnt = max(maxCnt, counter[ord(s[i]) - ord('A')]) - if i - j + 1 > maxCnt + k: - counter[ord(s[j]) - ord('A')] -= 1 - j += 1 - i += 1 - return i - j + 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 diff --git a/solution/0400-0499/0424.Longest Repeating Character Replacement/Solution.ts b/solution/0400-0499/0424.Longest Repeating Character Replacement/Solution.ts new file mode 100644 index 0000000000000..e6c82e5394f9c --- /dev/null +++ b/solution/0400-0499/0424.Longest Repeating Character Replacement/Solution.ts @@ -0,0 +1,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; +}