
2026-03-01:移除K-平衡子字符串。用go语言,给定一个只含左右括号的字符串 s 和一个正整数 k。
把恰好由 k 个连续左括号紧跟 k 个连续右括号组成的片段称为 k-平衡串(例如 k=3 时为 "((()))")。你需要反复进行如下操作:在当前字符串中选出若干互不重叠的 k-平衡子串,一次性将它们删掉,然后把剩下的部分重新拼接成新的字符串。不断重复这一过程,直到再也找不到任何 k-平衡子串为止。
注意这里的“子串”指的是原字符串中的连续片段。因为在选择删除的过程中可能存在不同的不重叠选择,最终可能得到多种不同的结果。返回所有可能的最终字符串。
2 <= s.length <= 100000。
s 仅由 '(' 和 ')' 组成。
1 <= k <= s.length / 2。
输入: s = "((()))()()()", k = 3
输出: "()()()"
解释:
k-平衡子串是 "((()))"
步骤 | 当前 s | k-平衡 | 结果 s |
|---|---|---|---|
1 | ((()))()()() | ((()))()()() | ()()() |
2 | ()()() | - | ()()() |
因此,最终字符串是 "()()()"。
题目来自力扣3703。
我们以输入 s = "((()))()()()"、k = 3 为例,结合代码逻辑拆解每一步执行过程:
代码中定义了 pair 结构体(保存「字符 + 连续出现次数」),并初始化一个栈 st(用于追踪连续括号的状态),最终结果 ans 初始化为空字节切片。
遍历顺序为:(、(、(、)、)、)、(、)、(、)、(、),逐个字符处理如下:
(:pair{b: '(', cnt: 1},此时栈内容:[{ '(', 1 }]。),无需触发「k-平衡串删除逻辑」。(:(,与当前字符相同,栈顶元素的 cnt 加1 → cnt = 2,栈内容:[{ '(', 2 }]。),无需触发删除逻辑。(:(,与当前字符相同,栈顶元素的 cnt 加1 → cnt = 3,栈内容:[{ '(', 3 }]。),无需触发删除逻辑。):(,与当前字符不同,向栈中添加 pair{b: ')', cnt: 1},此时栈内容:[{ '(', 3 }, { ')', 1 }]。),检查删除条件:))的 cnt = 1 ≠ 3(不满足),因此不执行删除。):),与当前字符相同,栈顶元素的 cnt 加1 → cnt = 2,栈内容:[{ '(', 3 }, { ')', 2 }]。),检查删除条件:))的 cnt = 2 ≠ 3(不满足),不执行删除。):),与当前字符相同,栈顶元素的 cnt 加1 → cnt = 3,栈内容:[{ '(', 3 }, { ')', 3 }]。),检查删除条件:))的 cnt = 3(等于k,满足);()的 cnt = 3(≥k,满足)。) 元素 → 栈内容变为 [{ '(', 3 }];()的 cnt 减去k → 3 - 3 = 0;cnt = 0,移除该 ( 元素 → 栈变为空。(:pair{b: '(', cnt: 1},栈内容:[{ '(', 1 }]。),无需删除。):(,与当前字符不同,添加 pair{b: ')', cnt: 1},栈内容:[{ '(', 1 }, { ')', 1 }]。),检查删除条件:))的 cnt = 1 ≠ 3(不满足),不删除。(:),与当前字符不同,添加 pair{b: '(', cnt: 1},栈内容:[{ '(', 1 }, { ')', 1 }, { '(', 1 }]。),无需删除。):(,与当前字符不同,添加 pair{b: ')', cnt: 1},栈内容:[{ '(', 1 }, { ')', 1 }, { '(', 1 }, { ')', 1 }]。),检查删除条件:))的 cnt = 1 ≠ 3(不满足),不删除。(:),与当前字符不同,添加 pair{b: '(', cnt: 1},栈内容:[{ '(', 1 }, { ')', 1 }, { '(', 1 }, { ')', 1 }, { '(', 1 }]。),无需删除。):(,与当前字符不同,添加 pair{b: ')', cnt: 1},栈内容:[{ '(', 1 }, { ')', 1 }, { '(', 1 }, { ')', 1 }, { '(', 1 }, { ')', 1 }]。),检查删除条件:))的 cnt = 1 ≠ 3(不满足),不删除。遍历完成后,栈中剩余的元素是:
[{ '(', 1 }, { ')', 1 }, { '(', 1 }, { ')', 1 }, { '(', 1 }, { ')', 1 }]
代码遍历栈中每个 pair,将「字符重复对应次数」拼接成字符串:
( 重复1次 → "(";) 重复1次 → ")";( 重复1次 → "(";) 重复1次 → ")";( 重复1次 → "(";) 重复1次 → ")";最终拼接结果为 "()()()",与题目预期输出一致。
代码通过「栈实时检测并删除k-平衡串」的方式,天然实现了「反复删除直到无k-平衡串」的逻辑:
st」:最坏情况下(无任何k-平衡串可删除),栈需要存储所有字符的 pair 结构,空间占用与n成正比;ans 最终存储的是处理后的字符串,属于输出空间,一般不计入「额外空间复杂度」;.
package main
import (
"fmt"
"strings"
)
func removeSubstring(s string, k int)string {
type pair struct {
b rune
cnt int
}
st := []pair{} // 栈中保存 pair{字符, 连续出现次数}
for _, b := range s {
iflen(st) > 0 && st[len(st)-1].b == b {
st[len(st)-1].cnt++ // 连续相同括号个数 +1
} else {
st = append(st, pair{b, 1}) // 新的括号
}
// 栈顶的 k 个右括号与栈顶下面的 k 个左括号抵消
if b == ')' && len(st) > 1 && st[len(st)-1].cnt == k && st[len(st)-2].cnt >= k {
st = st[:len(st)-1]
st[len(st)-1].cnt -= k
if st[len(st)-1].cnt == 0 {
st = st[:len(st)-1]
}
}
}
ans := []byte{}
for _, p := range st {
ans = append(ans, strings.Repeat(string(p.b), p.cnt)...)
}
returnstring(ans)
}
func main() {
s := "((()))()()()"
k := 3
result := removeSubstring(s, k)
fmt.Println(result)
}

.
# -*-coding:utf-8-*-
def remove_substring(s: str, k: int) -> str:
st = [] # 栈中保存 [字符, 连续出现次数]
for b in s:
if st and st[-1][0] == b:
st[-1][1] += 1 # 连续相同字符个数 +1
else:
st.append([b, 1]) # 新的字符
# 栈顶的 k 个右括号与栈顶下面的 k 个左括号抵消
if b == ')' and len(st) > 1 and st[-1][1] == k and st[-2][1] >= k:
st.pop() # 移除栈顶的 k 个右括号
st[-1][1] -= k # 左括号减少 k 个
if st[-1][1] == 0:
st.pop() # 如果左括号数量变为 0,也移除
# 构建结果字符串
result = []
for char, count in st:
result.append(char * count)
return''.join(result)
def main():
s = "((()))()()()"
k = 3
result = remove_substring(s, k)
print(result)
if __name__ == "__main__":
main()
.
#include <iostream>
#include <string>
#include <vector>
struct Pair {
char b; // 字符
int cnt; // 连续出现次数
};
std::string removeSubstring(std::string s, int k) {
std::vector<Pair> st; // 栈中保存 Pair{字符, 连续出现次数}
for (char b : s) {
if (!st.empty() && st.back().b == b) {
st.back().cnt++; // 连续相同字符个数 +1
} else {
st.push_back({b, 1}); // 新的字符
}
// 栈顶的 k 个右括号与栈顶下面的 k 个左括号抵消
if (b == ')' && st.size() > 1 && st.back().cnt == k && st[st.size() - 2].cnt >= k) {
st.pop_back(); // 移除栈顶的 k 个右括号
st.back().cnt -= k; // 左括号减少 k 个
if (st.back().cnt == 0) {
st.pop_back(); // 如果左括号数量变为 0,也移除
}
}
}
// 构建结果字符串
std::string result;
for (const auto& p : st) {
result.append(p.cnt, p.b); // 添加 p.cnt 个 p.b 字符
}
return result;
}
int main() {
std::string s = "((()))()()()";
int k = 3;
std::string result = removeSubstring(s, k);
std::cout << result << std::endl;
return0;
}

·
我们相信人工智能为普通人提供了一种“增强工具”,并致力于分享全方位的AI知识。在这里,您可以找到最新的AI科普文章、工具评测、提升效率的秘籍以及行业洞察。 欢迎关注“福大大架构师每日一题”,发消息可获得面试资料,让AI助力您的未来发展。
·