用切片模拟栈判断括号匹配最直接:左括号入栈,右括号需与栈顶配对,空栈时访问或遍历后栈非空均判失败;须用rune遍历防utf-8截断,用map映射括号提升可读性。

用 stack 切片模拟栈判断括号匹配最直接
Go 没有内置栈类型,但用切片([]rune 或 []byte)手动管理 top 索引,比引入第三方包更轻量、更可控。关键不是“用什么数据结构”,而是“何时 push / pop”——左括号无条件入栈,右括号必须和栈顶配对,否则立刻失败。
常见错误现象:panic: runtime error: index out of range,往往发生在没检查栈是否为空就执行 stack[len(stack)-1];或者遍历完字符串栈非空,漏判 "(((" 这类情况。
- 用
[]rune而非[]byte,避免中文或 emoji 导致的截断问题(LeetCode 输入虽多为 ASCII,但习惯要养) - 匹配逻辑别硬编码字符比较,用 map 做映射更清晰:
pair := map[rune]rune{')': '(', '}': '{', ']': '['} - 每次遇到右括号,先判断
len(stack) == 0,再取栈顶;不满足直接 return false
for range 遍历时别用 string[i] 取单个括号
Go 中 string 是字节序列,string[i] 拿到的是字节而非字符。遇到 Unicode 字符(哪怕只是测试时随手加了个中文注释),string[i] 可能返回一个不完整的 UTF-8 编码字节,导致括号识别错乱。LeetCode 测试用例虽是纯 ASCII,但写法一旦固化,后续在真实项目里容易翻车。
正确做法是用 for _, ch := range s,ch 类型是 rune,天然按字符迭代。
- 错误写法:
for i := 0; i —— 危险,尤其当 <code>s含非 ASCII 时 - 正确写法:
for _, ch := range s { ... },ch就是你要的括号字符 - 如果真要用索引(比如想跳过某些位置),先转成
[]rune(s)再操作,别直接索引原 string
闭括号不匹配时,return false 要立即发生
很多人写成“收集所有不匹配再统一返回”,结果多绕一圈还容易漏逻辑。有效括号题的核心约束是:任意前缀中,右括号数量不能超过左括号;且最终左右数量必须相等。这意味着只要出现一次无法配对的右括号,整个字符串就已确定非法。
Go 配置库,使用 spf13/viper — 分层优先级(flag > env >file > KV > default),提供 BindPFlag/BindPFlags、SetEnvPrefix + SetEnvKeyReplace 等功能。
典型错误场景:s = "([)]"。遇到 ')' 时,栈顶是 '[',不匹配,此时必须立刻 return false,而不是继续往后看。
- 不要写
if ch is right && stack[top] != left → flag = false然后继续循环 - 也不要等循环结束再检查 flag,那会错过
")()"这种开头就错的情况 - 右括号不匹配、栈为空、循环结束后栈非空——这三个条件任一成立,就 return false
LeetCode 提交时注意 func isValid(s string) bool 的签名别改
函数名、参数类型、返回值类型必须完全一致,否则编译失败。常见手误:把 string 写成 []byte,或返回 int(比如 0/1),或加了多余参数(如 stack 作为入参)。Go 是强类型语言,不会自动转换。
另外,本地测试时如果用 fmt.Println 调试,提交前务必删掉——LeetCode 对输出内容敏感,多打一行就 WA(Wrong Answer)。
- 签名必须严格为:
func isValid(s string) bool - 别导出内部变量名(如
Stack大写),LeetCode 运行环境不认包外定义 - 性能上不用过度优化:O(n) 时间 + O(n) 空间已是理论最优,无需强行改成 O(1) 空间(不可行)
括号匹配看着简单,真正卡住人的永远是边界:空字符串怎么算(合法)、单个括号怎么算(非法)、嵌套深度极大时栈会不会爆(不会,LeetCode 有长度限制)——这些点不靠背结论,得在 if 分支里亲手写出来才踏实。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










