diff --git a/solution/3700-3799/3703.Remove K-Balanced Substrings/README.md b/solution/3700-3799/3703.Remove K-Balanced Substrings/README.md index 78daee6fd05d5..5d909cc123514 100644 --- a/solution/3700-3799/3703.Remove K-Balanced Substrings/README.md +++ b/solution/3700-3799/3703.Remove K-Balanced Substrings/README.md @@ -162,32 +162,146 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3700-3799/3703.Re -### 方法一 +### 方法一:栈 + +我们用一个栈来维护当前字符串的状态。栈中的每个元素是一个二元组,表示某个字符及其连续出现的次数。 + +遍历字符串中的每个字符: + +- 如果栈不为空且栈顶元素的字符与当前字符相同,则将栈顶元素的计数加一。 +- 否则,将当前字符和计数 1 作为一个新元素压入栈中。 +- 如果当前字符是 `')'`,且栈中至少有两个元素,且栈顶元素的计数等于 $k$,且栈顶元素的前一个元素的计数大于等于 $k$,则弹出栈顶元素,并将前一个元素的计数减去 $k$。如果前一个元素的计数变为 0,则也将其弹出。 + +遍历结束后,栈中剩下的元素即为最终字符串的状态。我们将这些元素按顺序连接起来,得到结果字符串。 + +时间复杂度 $O(n)$,空间复杂度 $O(n)$,其中 $n$ 是字符串 $s$ 的长度。 #### Python3 ```python - +class Solution: + def removeSubstring(self, s: str, k: int) -> str: + stk = [] + for c in s: + if stk and stk[-1][0] == c: + stk[-1][1] += 1 + else: + stk.append([c, 1]) + if c == ")" and len(stk) > 1 and stk[-1][1] == k and stk[-2][1] >= k: + stk.pop() + stk[-1][1] -= k + if stk[-1][1] == 0: + stk.pop() + return "".join(c * v for c, v in stk) ``` #### Java ```java - +class Solution { + public String removeSubstring(String s, int k) { + List stk = new ArrayList<>(); + for (char c : s.toCharArray()) { + if (!stk.isEmpty() && stk.get(stk.size() - 1)[0] == c) { + stk.get(stk.size() - 1)[1] += 1; + } else { + stk.add(new int[]{c, 1}); + } + if (c == ')' && stk.size() > 1) { + int[] top = stk.get(stk.size() - 1); + int[] prev = stk.get(stk.size() - 2); + if (top[1] == k && prev[1] >= k) { + stk.remove(stk.size() - 1); + prev[1] -= k; + if (prev[1] == 0) { + stk.remove(stk.size() - 1); + } + } + } + } + StringBuilder sb = new StringBuilder(); + for (int[] pair : stk) { + for (int i = 0; i < pair[1]; i++) { + sb.append((char) pair[0]); + } + } + return sb.toString(); + } +} ``` #### C++ ```cpp - +class Solution { +public: + string removeSubstring(string s, int k) { + vector> stk; + for (char c : s) { + if (!stk.empty() && stk.back().first == c) { + stk.back().second += 1; + } else { + stk.emplace_back(c, 1); + } + if (c == ')' && stk.size() > 1) { + auto& top = stk.back(); + auto& prev = stk[stk.size() - 2]; + if (top.second == k && prev.second >= k) { + stk.pop_back(); + prev.second -= k; + if (prev.second == 0) { + stk.pop_back(); + } + } + } + } + string res; + for (auto& p : stk) { + res.append(p.second, p.first); + } + return res; + } +}; ``` #### Go ```go - +func removeSubstring(s string, k int) string { + type pair struct { + ch byte + count int + } + stk := make([]pair, 0) + for i := 0; i < len(s); i++ { + c := s[i] + if len(stk) > 0 && stk[len(stk)-1].ch == c { + stk[len(stk)-1].count++ + } else { + stk = append(stk, pair{c, 1}) + } + if c == ')' && len(stk) > 1 { + top := &stk[len(stk)-1] + prev := &stk[len(stk)-2] + if top.count == k && prev.count >= k { + stk = stk[:len(stk)-1] + prev.count -= k + if prev.count == 0 { + stk = stk[:len(stk)-1] + } + } + } + } + res := make([]byte, 0) + for _, p := range stk { + for i := 0; i < p.count; i++ { + res = append(res, p.ch) + } + } + return string(res) +} ``` diff --git a/solution/3700-3799/3703.Remove K-Balanced Substrings/README_EN.md b/solution/3700-3799/3703.Remove K-Balanced Substrings/README_EN.md index f0a377517e8e0..be0c488d71f75 100644 --- a/solution/3700-3799/3703.Remove K-Balanced Substrings/README_EN.md +++ b/solution/3700-3799/3703.Remove K-Balanced Substrings/README_EN.md @@ -157,32 +157,146 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3700-3799/3703.Re -### Solution 1 +### Solution 1: Stack + +We use a stack to maintain the current state of the string. Each element in the stack is a pair representing a character and its consecutive count. + +Traverse each character in the string: + +- If the stack is not empty and the character of the top element matches the current character, increment the count of the top element. +- Otherwise, push the current character with count 1 as a new element onto the stack. +- If the current character is `')'`, and there are at least two elements in the stack, and the count of the top element equals $k$, and the count of the previous element is greater than or equal to $k$, then pop the top element and subtract $k$ from the count of the previous element. If the count of the previous element becomes 0, pop it as well. + +After traversal, the remaining elements in the stack represent the final state of the string. We concatenate these elements in order to get the result string. + +The time complexity is $O(n)$ and the space complexity is $O(n)$, where $n$ is the length of string $s$. #### Python3 ```python - +class Solution: + def removeSubstring(self, s: str, k: int) -> str: + stk = [] + for c in s: + if stk and stk[-1][0] == c: + stk[-1][1] += 1 + else: + stk.append([c, 1]) + if c == ")" and len(stk) > 1 and stk[-1][1] == k and stk[-2][1] >= k: + stk.pop() + stk[-1][1] -= k + if stk[-1][1] == 0: + stk.pop() + return "".join(c * v for c, v in stk) ``` #### Java ```java - +class Solution { + public String removeSubstring(String s, int k) { + List stk = new ArrayList<>(); + for (char c : s.toCharArray()) { + if (!stk.isEmpty() && stk.get(stk.size() - 1)[0] == c) { + stk.get(stk.size() - 1)[1] += 1; + } else { + stk.add(new int[]{c, 1}); + } + if (c == ')' && stk.size() > 1) { + int[] top = stk.get(stk.size() - 1); + int[] prev = stk.get(stk.size() - 2); + if (top[1] == k && prev[1] >= k) { + stk.remove(stk.size() - 1); + prev[1] -= k; + if (prev[1] == 0) { + stk.remove(stk.size() - 1); + } + } + } + } + StringBuilder sb = new StringBuilder(); + for (int[] pair : stk) { + for (int i = 0; i < pair[1]; i++) { + sb.append((char) pair[0]); + } + } + return sb.toString(); + } +} ``` #### C++ ```cpp - +class Solution { +public: + string removeSubstring(string s, int k) { + vector> stk; + for (char c : s) { + if (!stk.empty() && stk.back().first == c) { + stk.back().second += 1; + } else { + stk.emplace_back(c, 1); + } + if (c == ')' && stk.size() > 1) { + auto& top = stk.back(); + auto& prev = stk[stk.size() - 2]; + if (top.second == k && prev.second >= k) { + stk.pop_back(); + prev.second -= k; + if (prev.second == 0) { + stk.pop_back(); + } + } + } + } + string res; + for (auto& p : stk) { + res.append(p.second, p.first); + } + return res; + } +}; ``` #### Go ```go - +func removeSubstring(s string, k int) string { + type pair struct { + ch byte + count int + } + stk := make([]pair, 0) + for i := 0; i < len(s); i++ { + c := s[i] + if len(stk) > 0 && stk[len(stk)-1].ch == c { + stk[len(stk)-1].count++ + } else { + stk = append(stk, pair{c, 1}) + } + if c == ')' && len(stk) > 1 { + top := &stk[len(stk)-1] + prev := &stk[len(stk)-2] + if top.count == k && prev.count >= k { + stk = stk[:len(stk)-1] + prev.count -= k + if prev.count == 0 { + stk = stk[:len(stk)-1] + } + } + } + } + res := make([]byte, 0) + for _, p := range stk { + for i := 0; i < p.count; i++ { + res = append(res, p.ch) + } + } + return string(res) +} ``` diff --git a/solution/3700-3799/3703.Remove K-Balanced Substrings/Solution.cpp b/solution/3700-3799/3703.Remove K-Balanced Substrings/Solution.cpp new file mode 100644 index 0000000000000..0d6430e2bfa95 --- /dev/null +++ b/solution/3700-3799/3703.Remove K-Balanced Substrings/Solution.cpp @@ -0,0 +1,29 @@ +class Solution { +public: + string removeSubstring(string s, int k) { + vector> stk; + for (char c : s) { + if (!stk.empty() && stk.back().first == c) { + stk.back().second += 1; + } else { + stk.emplace_back(c, 1); + } + if (c == ')' && stk.size() > 1) { + auto& top = stk.back(); + auto& prev = stk[stk.size() - 2]; + if (top.second == k && prev.second >= k) { + stk.pop_back(); + prev.second -= k; + if (prev.second == 0) { + stk.pop_back(); + } + } + } + } + string res; + for (auto& p : stk) { + res.append(p.second, p.first); + } + return res; + } +}; diff --git a/solution/3700-3799/3703.Remove K-Balanced Substrings/Solution.go b/solution/3700-3799/3703.Remove K-Balanced Substrings/Solution.go new file mode 100644 index 0000000000000..6f91ad131dcf9 --- /dev/null +++ b/solution/3700-3799/3703.Remove K-Balanced Substrings/Solution.go @@ -0,0 +1,33 @@ +func removeSubstring(s string, k int) string { + type pair struct { + ch byte + count int + } + stk := make([]pair, 0) + for i := 0; i < len(s); i++ { + c := s[i] + if len(stk) > 0 && stk[len(stk)-1].ch == c { + stk[len(stk)-1].count++ + } else { + stk = append(stk, pair{c, 1}) + } + if c == ')' && len(stk) > 1 { + top := &stk[len(stk)-1] + prev := &stk[len(stk)-2] + if top.count == k && prev.count >= k { + stk = stk[:len(stk)-1] + prev.count -= k + if prev.count == 0 { + stk = stk[:len(stk)-1] + } + } + } + } + res := make([]byte, 0) + for _, p := range stk { + for i := 0; i < p.count; i++ { + res = append(res, p.ch) + } + } + return string(res) +} diff --git a/solution/3700-3799/3703.Remove K-Balanced Substrings/Solution.java b/solution/3700-3799/3703.Remove K-Balanced Substrings/Solution.java new file mode 100644 index 0000000000000..1fab503ddca05 --- /dev/null +++ b/solution/3700-3799/3703.Remove K-Balanced Substrings/Solution.java @@ -0,0 +1,30 @@ +class Solution { + public String removeSubstring(String s, int k) { + List stk = new ArrayList<>(); + for (char c : s.toCharArray()) { + if (!stk.isEmpty() && stk.get(stk.size() - 1)[0] == c) { + stk.get(stk.size() - 1)[1] += 1; + } else { + stk.add(new int[]{c, 1}); + } + if (c == ')' && stk.size() > 1) { + int[] top = stk.get(stk.size() - 1); + int[] prev = stk.get(stk.size() - 2); + if (top[1] == k && prev[1] >= k) { + stk.remove(stk.size() - 1); + prev[1] -= k; + if (prev[1] == 0) { + stk.remove(stk.size() - 1); + } + } + } + } + StringBuilder sb = new StringBuilder(); + for (int[] pair : stk) { + for (int i = 0; i < pair[1]; i++) { + sb.append((char) pair[0]); + } + } + return sb.toString(); + } +} diff --git a/solution/3700-3799/3703.Remove K-Balanced Substrings/Solution.py b/solution/3700-3799/3703.Remove K-Balanced Substrings/Solution.py new file mode 100644 index 0000000000000..b153a426a33c2 --- /dev/null +++ b/solution/3700-3799/3703.Remove K-Balanced Substrings/Solution.py @@ -0,0 +1,14 @@ +class Solution: + def removeSubstring(self, s: str, k: int) -> str: + stk = [] + for c in s: + if stk and stk[-1][0] == c: + stk[-1][1] += 1 + else: + stk.append([c, 1]) + if c == ")" and len(stk) > 1 and stk[-1][1] == k and stk[-2][1] >= k: + stk.pop() + stk[-1][1] -= k + if stk[-1][1] == 0: + stk.pop() + return "".join(c * v for c, v in stk)