题目: 1614. 括号的最大嵌套深度
标签: 字符串 · 计数
题目描述
给定一个括号匹配正确的字符串 s,返回其中括号的最大嵌套层数 。没有括号时,深度为 0。
这里数的是最多套了多少层,不是有多少对括号。比如 ()() 有两对括号,但它们并排出现,深度只有 1;(()) 才是两层。
text
输入:s = "(1+(2*3)+((8)/4))+1"
输出:3
数字 8 外面套着三层括号,因此答案是 3。不需要计算表达式的结果。
数据范围:
1 <= s.length <= 100。- 字符只包含数字
0~9,以及+、-、*、/、(、)。 - 题目保证括号匹配有效,不需要另外判断是否合法。
深度,就是还没闭合的左括号数量
从左到右读字符串时,可以把每个左括号看成"进入一层",每个右括号看成"退出一层"。
用 depth 记录当前层数,初始为 0:
- 遇到
(:depth加一。 - 遇到
):depth减一。 - 遇到数字或运算符:层数不变。
每个还没被右括号配对的左括号,都代表一层尚未退出的括号。 所以这个计数就等于当前深度。
再用 answer 记录 depth 出现过的最大值,就是题目要的答案。只有遇到左括号时,深度才可能刷新最大值。
如果使用栈,可以遇到左括号就放入一个元素,遇到右括号就移除最近放入的元素。但这题只关心还剩几个,不需要保存每个括号的位置或内容,一个计数器就够了。
跟着例子走一遍
数字和运算符不影响层数。为了看清变化,先只看示例中的括号:
text
原字符串:(1+(2*3)+((8)/4))+1
只看括号:(()(()))
实际代码直接扫描原字符串,不需要提前删除其他字符。
初始 depth = 0,answer = 0:
| 读到第几个括号 | 字符 | 当前深度 depth | 最大深度 answer |
|---|---|---|---|
| 1 | ( |
1 | 1 |
| 2 | ( |
2 | 2 |
| 3 | ) |
1 | 2 |
| 4 | ( |
2 | 2 |
| 5 | ( |
3 | 3 |
| 6 | ) |
2 | 3 |
| 7 | ) |
1 | 3 |
| 8 | ) |
0 | 3 |
第 5 个括号读完时,到达最深的第 3 层,也就是数字 8 所在的位置。
最后 depth 回到了 0,但答案仍是 3。我们要的是过程中最深到过哪里,而不是结束时还剩几层。
C++ 实现
cpp
#include <string>
class Solution {
public:
int maxDepth(const std::string& s) {
int depth = 0;
int answer = 0;
for (char ch : s) {
if (ch == '(') {
++depth;
if (depth > answer) {
answer = depth;
}
} else if (ch == ')') {
--depth;
}
}
return answer;
}
};
C 实现
c
int maxDepth(char* s) {
int depth = 0;
int answer = 0;
for (int i = 0; s[i] != '\0'; ++i) {
if (s[i] == '(') {
++depth;
if (depth > answer) {
answer = depth;
}
} else if (s[i] == ')') {
--depth;
}
}
return answer;
}
设字符串长度为 n,只扫描一次,时间复杂度为 O(n) 。只使用固定数量的变量,额外空间为 O(1)。C++ 通过常量引用读取字符串,两版都不复制或修改输入内容。
容易写错的地方
- 先加一,再更新最大值。 遇到左括号就已经进入了新的一层。
- 不能把所有非左括号都当成右括号。 数字和运算符应当直接跳过,所以代码使用
else if判断)。 - 返回
answer,不是depth。 有效括号全部处理完后,当前深度一定回到0。
也别把深度当成"连续左括号的最大数量":示例里最多连续出现两个左括号,深度却能达到 3,因为外面还有一层没有闭合。
这套思路还能用在哪?
做一个简单的表达式编辑器时,可以根据当前深度给括号分层着色;编写解析程序时,也可以检查嵌套层数是否超过预设上限。
迁移到真实代码文本时,需要先识别字符串、注释等内容,避免把里面的普通括号算成结构。若要检查 ()、[]、{} 是否正确匹配,还得记录括号类型和顺序,不能只用一个计数器判断。
看到"进入一层、退出一层、求最深层数",可以先想想:是否只需维护当前层数,以及它达到过的最大值。