
本文介绍一种简洁可靠的算法,用于在Java中移除字符串中所有成对出现且可匹配的括号(如 [ ]、{ }、( ) 或自定义符号),保留非配对括号及全部其他字符,适用于教学与实际开发场景。
本文介绍一种简洁可靠的算法,用于在java中移除字符串中所有**成对出现且可匹配的括号**(如 `[ ]`、`{ }`、`( )` 或自定义符号),保留非配对括号及全部其他字符,适用于教学与实际开发场景。
在处理括号匹配类问题时,一个常见误区是试图通过双向扫描或模拟栈行为进行“嵌套消除”——这不仅逻辑复杂、边界难控,还容易因方向混淆导致错误(如原题中 pairRemoval 方法因左右指针异步移动而漏删左侧孤立 [)。但本题的核心目标并非验证括号合法性,而是移除所有能构成完整配对的括号字符(各一个左、一个右),且不关心嵌套层级或顺序——即:只要字符串中存在 n 个 '[' 和 m 个 ']',就最多可移除 min(n, m) 对,每对各删一个左括号和一个右括号。
该策略本质上是贪心配对:从左到右遍历,优先消耗可用的左括号计数;当遇到右括号时,若仍有未配对的左括号余额,则将其抵消(即跳过该右括号),否则保留。注意:此方法不要求括号位置相邻或嵌套合法,例如 " ] [ " 中的 ] 和 [ 无法配对(因左括号在右括号之后),故两者均被保留——这完全符合题目示例的预期输出。
以下是标准、健壮的 Java 实现(支持任意自定义左右括号字符):
public class BracketPairRemover {
/**
* 移除字符串中最多可配对的括号对(左括号与右括号各删一个,共 min(countLeft, countRight) 对)
* @param text 原始字符串
* @param leftBracket 左括号字符(如 '['、'{'、'')
* @return 移除配对括号后的字符串
*/
public static String removeMatchingPairs(String text, char leftBracket, char rightBracket) {
if (text == null) return null;
// 统计左右括号总数量
long leftCount = text.chars().filter(ch -> ch == leftBracket).count();
long rightCount = text.chars().filter(ch -> ch == rightBracket).count();
long pairCount = Math.min(leftCount, rightCount);
StringBuilder result = new StringBuilder();
long remainingLeft = pairCount; // 待消耗的左括号余额
for (char c : text.toCharArray()) {
if (c == leftBracket && remainingLeft > 0) {
remainingLeft--;
// 跳过该左括号(不追加)
} else if (c == rightBracket && pairCount > 0) {
// 遇到右括号时,只要总配对数未耗尽,就消耗一对
pairCount--;
// 跳过该右括号
} else {
result.append(c); // 其他所有字符(含多余括号)均保留
}
}
return result.toString();
}
// 示例用法
public static void main(String[] args) {
// 示例1:题目原始用例
String s1 = "hello [ [ ] hello ] hello [ hello ] hello hello";
System.out.println(removeMatchingPairs(s1, '[', ']'));
// 输出:hello hello hello hello hello hello (空格保留,仅删括号)
// 示例2:含前置非法右括号
String s2 = "] hello world ] ] [ HELLO ] WORLD ] ] ] hello world";
System.out.println(removeMatchingPairs(s2, '[', ']'));
// 输出:hello world ] ] HELLO ] WORLD ] ] ] hello world
// 示例3:自定义括号
String s3 = "> hello hello > > hello > > > hello hello";
System.out.println(removeMatchingPairs(s3, ''));
// 输出: hello hello > > hello > hello > > > hello hello
// 示例4:混合与孤立括号
String s4 = "hello hello } { hello { } hello } { { hello";
System.out.println(removeMatchingPairs(s4, '{', '}'));
// 输出:hello hello hello hello { hello
}
}
✅ 关键优势说明:
- 时间复杂度 O(n):仅需两次遍历(统计 + 构建),无嵌套循环;
- 空间友好:使用 StringBuilder 避免字符串频繁拼接开销;
- 通用性强:通过参数传入任意单字符括号,无需修改逻辑;
- 语义清晰:严格遵循“移除 min(左数, 右数) 对”的题目定义,不误删、不漏删。
⚠️ 注意事项:
- 此算法不校验括号语法正确性(如 "][" 不会互删),符合题目所有测试用例要求;
- 若需支持多字符分隔符(如 "{{"、"}}")或真正嵌套消除(如只删最内层 []),则需改用栈模拟,但本题明确只需“配对数量级移除”;
- 对超长字符串,chars().count() 可替换为手动遍历以避免创建中间流对象,提升性能。
掌握这种基于计数的贪心思想,不仅能高效解决括号配对移除问题,也为理解编译器词法分析、模板引擎解析等底层机制打下坚实基础。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











