用栈检查括号匹配最可靠,需用std::stack模拟就近匹配:左括号入栈,右括号时查栈顶是否匹配,栈空或不匹配则返回false,遍历完栈必须为空;映射用unordered_map预存右括号到左括号关系;跳过非括号字符;空串和纯文本均合法。

用 stack 检查括号匹配是最直接可靠的方式
遇到 {[()]} 这类混合括号,靠计数器或正则根本不可行——不同括号类型有嵌套顺序约束,必须用栈模拟“就近匹配”逻辑。C++ 标准库的 std::stack 足够轻量且语义清晰,别自己手写链表或 vector 模拟栈。
核心思路:遍历字符串,左括号入栈,右括号时检查栈顶是否为对应左括号;不匹配或栈空时直接返回 false;遍历完栈必须为空才算合法。
常见错误现象:std::stack<char></char> 存的是字符,但比较时忘了用单引号写成 '(' 而不是 "(";或者没处理栈空就调用 top() 导致崩溃。
- 只用
std::stack,不用std::vector或std::deque做栈——它们支持随机访问,反而容易误操作 - 提前退出:遇到不匹配右括号(如
"]"对应栈顶是'{')或栈空时还试图top(),立刻 return false - 结尾必须检查
stack.empty():否则"((["会被误判为合法
如何高效映射右括号到对应左括号
硬编码 if-else 判断 ch == ')' && stk.top() == '(' 可读性差、易漏 case。推荐用 std::unordered_map 预定义映射关系,把 “右括号 → 左括号” 关系固化下来,代码更健壮也方便扩展新括号对。
立即学习“C++免费学习笔记(深入)”;
注意:map 的 key 是右括号(')'、']'、'}'),value 是对应左括号;左括号不进 map,只用于入栈。
性能影响很小——map 查找是 O(1) 平均复杂度,且只在右括号分支触发,不影响整体线性时间。
- 初始化 map 用列表初始化:
std::unordered_map<char char> pairs = {{')', '('}, {']', '['}, {'}', '{'}};</char> - 查 map 前先用
pairs.count(ch)判断是否为右括号,避免operator[]插入默认值 - 不要把
'('、'['等也塞进 map 当 key——逻辑混淆,增加无谓查找
忽略非括号字符的边界处理
题目说“字符串的括号平衡性校验”,隐含前提:字符串中可能混杂字母、数字、空格等无关字符。这些必须跳过,不能当成非法字符直接报错。
典型场景:校验 JSON 片段 "{ \"name\": \"[a]\" }" 或代码片段 "if (x > 0) { return [1,2]; }" ——引号、运算符、字母全要无视。
容易踩的坑:用 isalnum() 或 isspace() 排除非括号,但漏掉标点(如 ','、'.')导致误判;更稳妥的是显式判断是否属于六种括号字符。
- 只对
'('、')'、'['、']'、'{'、'}'做处理,其余字符一律 continue - 别用
std::string::find_first_of("()[]{}")循环查找——破坏遍历的 O(n) 时间保证 - 如果需求明确要求“字符串仅含括号”,那可以加一步预检,但多数真实场景不需此限制
考虑空字符串和全非括号字符串的返回值
空字符串 "" 和纯文本字符串如 "hello world" 都应返回 true——因为“没有不平衡的括号”即满足平衡性定义。这点常被忽略,测试用例一跑就挂。
实现上无需特殊处理:循环跳过所有字符后栈为空,自然返回 true。但如果你在循环前加了非空校验或提前 return,就会出错。
另一个易错点:输入含 null 字符('\0')或宽字符,但标准 C++ std::string 不含内部 null,只要用 str[i] 或 range-for 遍历就安全。
- 不要写
if (s.empty()) return true;——冗余,且掩盖逻辑一致性 - 避免用 C 风格
for (int i = 0; s[i]; ++i),万一字符串含 '\0' 就截断(虽然 std::string 不该有,但防御性编程不依赖这个) - range-for 最稳妥:
for (char ch : s) { /* ... */ }
实际校验逻辑里最脆弱的一环,是忘记在右括号分支做栈空检查——stack.top() 前没判空,程序直接崩溃。这比算法选错还致命。


















