题目
标题和出处
标题:括号的最大嵌套深度
难度
2 级
题目描述
要求
如果字符串满足以下条件之一,则可以称之为有效括号字符串:
- 字符串是一个空字符串 "" \texttt{""} "",或者是一个不为 "(" \texttt{"("} "(" 或 ")" \texttt{")"} ")" 的单字符。
- 字符串可以写为 AB \texttt{AB} AB( A \texttt{A} A 与 B \texttt{B} B 字符串连接),其中 A \texttt{A} A 和 B \texttt{B} B 都是有效括号字符串。
- 字符串可以写为 (A) \texttt{(A)} (A),其中 A \texttt{A} A 是一个有效括号字符串。
类似地,可以定义任何有效括号字符串 S \texttt{S} S 的嵌套深度 depth(S) \texttt{depth(S)} depth(S):
- depth("") = 0 \texttt{depth("") = 0} depth("") = 0
- depth(C) = 0 \texttt{depth(C) = 0} depth(C) = 0,其中 C \texttt{C} C 是单个字符的字符串,且该字符不是 "(" \texttt{"("} "(" 或者 ")" \texttt{")"} ")"
- depth(A + B) = max(depth(A), depth(B)) \texttt{depth(A + B) = max(depth(A), depth(B))} depth(A + B) = max(depth(A), depth(B)),其中 A \texttt{A} A 和 B \texttt{B} B 都是有效括号字符串
- depth("(" + A + ")") = 1 + depth(A) \texttt{depth("(" + A + ")") = 1 + depth(A)} depth("(" + A + ")") = 1 + depth(A),其中 A \texttt{A} A 是一个有效括号字符串
例如: "" \texttt{""} ""、 "()()" \texttt{"()()"} "()()"、 "()(()())" \texttt{"()(()())"} "()(()())" 都是有效括号字符串(嵌套深度分别为 0 \texttt{0} 0、 1 \texttt{1} 1、 2 \texttt{2} 2),而 ")(" \texttt{")("} ")("、 "(()" \texttt{"(()"} "(()" 都不是有效括号字符串。
给你一个有效括号字符串 s \texttt{s} s,返回该字符串 s \texttt{s} s 的嵌套深度。
示例
示例 1:
输入:
s
=
"(1+(2*3)+((8)/4))+1"
\texttt{s = "(1+(2*3)+((8)/4))+1"}
s = "(1+(2*3)+((8)/4))+1"
输出:
3
\texttt{3}
3
解释:数字
8
\texttt{8}
8 在嵌套的
3
\texttt{3}
3 层括号中。
示例 2:
输入:
s
=
"(1)+((2))+(((3)))"
\texttt{s = "(1)+((2))+(((3)))"}
s = "(1)+((2))+(((3)))"
输出:
3
\texttt{3}
3
示例 3:
输入:
s
=
"1+(2*3)/(2-1)"
\texttt{s = "1+(2*3)/(2-1)"}
s = "1+(2*3)/(2-1)"
输出:
1
\texttt{1}
1
示例 4:
输入:
s
=
"1"
\texttt{s = "1"}
s = "1"
输出:
0
\texttt{0}
0
数据范围
- 1 ≤ s.length ≤ 100 \texttt{1} \le \texttt{s.length} \le \texttt{100} 1≤s.length≤100
- s \texttt{s} s 由数字 0-9 \texttt{0-9} 0-9 和字符 ‘+’ \texttt{`+'} ‘+’、 ‘-’ \texttt{`-'} ‘-’、 ‘*’ \texttt{`*'} ‘*’、 ‘/’ \texttt{`/'} ‘/’、 ‘(’ \texttt{`('} ‘(’、 ‘)’ \texttt{`)'} ‘)’ 组成
- 题目数据保证括号表达式 s \texttt{s} s 是有效的括号表达式
解法一
思路和算法
根据题目描述,给定的字符串 s s s 是有效括号字符串,其嵌套深度只取决于字符串中的括号字符,因此只要考虑字符串中的左括号和右括号。在有效括号字符串中,左括号和右括号的数量相同且形成匹配,因此最大嵌套深度的计算方法为计算任意位置的尚未匹配的左括号的数量。
可以使用栈存储左括号,栈内元素个数即为嵌套深度。
从左到右遍历字符串 s s s,遇到左括号则将左括号入栈,遇到右括号则将栈顶的左括号出栈,表示当前的右括号和栈顶的左括号匹配。遍历到任意位置时,栈内的左括号都是尚未匹配的左括号,在尚未遍历到的字符中将会有相同数量的右括号和这些左括号匹配,因此当前位置的嵌套深度即为栈内的左括号数量。在所有位置中,栈内的左括号数量的最大值即为字符串 s s s 的嵌套深度。
代码
class Solution {
public int maxDepth(String s) {
int depth = 0;
Deque<Character> stack = new ArrayDeque<Character>();
int length = s.length();
for (int i = 0; i < length; i++) {
char c = s.charAt(i);
if (c == '(') {
stack.push(c);
} else if (c == ')') {
stack.pop();
}
depth = Math.max(depth, stack.size());
}
return depth;
}
}
复杂度分析
-
时间复杂度: O ( n ) O(n) O(n),其中 n n n 是字符串 s s s 的长度。需要遍历字符串 s s s 一次,每次入栈和出栈操作的时间都是 O ( 1 ) O(1) O(1)。
-
空间复杂度: O ( n ) O(n) O(n),其中 n n n 是字符串 s s s 的长度。空间复杂度主要取决于栈空间,栈内的元素个数为 O ( n ) O(n) O(n)。
解法二
思路和算法
也可以不用栈,而是使用计数的方式计算字符串的嵌套深度。
具体做法是,使用 depth \textit{depth} depth 记录最大嵌套深度,使用 count \textit{count} count 记录未匹配的左括号的数量,初始时 depth = count = 0 \textit{depth} = \textit{count} = 0 depth=count=0。遍历字符串 s s s,遇到左括号则将 count \textit{count} count 加 1 1 1,遇到右括号则将 count \textit{count} count 减 1 1 1,在整个过程中维护 depth \textit{depth} depth 的值。遍历结束之后, depth \textit{depth} depth 即为最大嵌套深度。
代码
class Solution {
public int maxDepth(String s) {
int depth = 0;
int count = 0;
int length = s.length();
for (int i = 0; i < length; i++) {
char c = s.charAt(i);
if (c == '(') {
count++;
} else if (c == ')') {
count--;
}
depth = Math.max(depth, count);
}
return depth;
}
}
复杂度分析
-
时间复杂度: O ( n ) O(n) O(n),其中 n n n 是字符串 s s s 的长度。需要遍历字符串 s s s 一次,每次更新计数的时间都是 O ( 1 ) O(1) O(1)。
-
空间复杂度: O ( 1 ) O(1) O(1)。