M1111.有效括号的嵌套深度
stack, https://leetcode.cn/problems/maximum-nesting-depth-of-two-valid-parentheses-strings/
如果一个字符串仅由字符 "(" 和 ")" 组成,并且满足以下条件,则称为有效括号字符串(VPS):
- 它是空字符串,或
- 它可以表示为
AB(A连接B),其中A和B都是VPS,或者 - 它可以表示为
(A),其中A是一个 VPS。
我们可以类似地定义任何 VPS S 的嵌套深度 depth(S) 如下:
depth("") = 0depth(A + B) = max(depth(A), depth(B)),其中A和B都是 VPSdepth("(" + A + ")") = 1 + depth(A),其中A是一个 VPS。
例如,"","()()" 和 "()(()())" 都是 VPS(嵌套深度 0,1 和 2),并且 ")(" 和 "(()" 不是 VPS。
给定一个 VPS 序列,将其拆分成两个不相交的子序列 A 和 B,使得 A 和 B 都是 VPS(且 A.length + B.length = seq.length)。这些子序列不一定是连续的。
例如,对于序列 123456789,一种可能的拆分是:
A = {1, 3, 5, 7, 9},B = {2, 4, 6, 8}。- 这对应于输出
[0, 1, 0, 1, 0, 1, 0, 1, 0],其中 0 表示属于A,1 表示属于B。
现在选择 任意 这样的 A 和 B,使得 max(depth(A), depth(B)) 的值是最小的。
返回一个 answer 数组(长度为 seq.length),该数组编码了 A 和 B 的选择:如果 seq[i] 是 A 的一部分则 answer[i] = 0,否则 answer[i] = 1。请注意,尽管可能存在多种答案,但你可以返回其中任意一种。
示例 1:
输入:seq = "(()())"
输出:[0,1,1,1,1,0]示例 2:
输入:seq = "()(())()"
输出:[0,0,0,1,1,0,1,1]
解释:本示例答案不唯一。
按此输出 A = "()()", B = "()()", max(depth(A), depth(B)) = 1,它们的深度最小。
像 [1,1,1,0,0,1,1,1],也是正确结果,其中 A = "()()()", B = "()", max(depth(A), depth(B)) = 1 。提示:
1 < seq.size <= 10000
有效括号字符串:
仅由 "(" 和 ")" 构成的字符串,对于每个左括号,都能找到与之对应的右括号,反之亦然。
下述几种情况同样属于有效括号字符串:
1. 空字符串
2. 连接,可以记作 AB(A 与 B 连接),其中 A 和 B 都是有效括号字符串
3. 嵌套,可以记作 (A),其中 A 是有效括号字符串嵌套深度:
类似地,我们可以定义任意有效括号字符串 s 的 嵌套深度 depth(S):
1. s 为空时,depth("") = 0
2. s 为 A 与 B 连接时,depth(A + B) = max(depth(A), depth(B)),其中 A 和 B 都是有效括号字符串
3. s 为嵌套情况,depth("(" + A + ")") = 1 + depth(A),其中 A 是有效括号字符串
例如:"","()()",和 "()(()())" 都是有效括号字符串,嵌套深度分别为 0,1,2,而 ")(" 和 "(()" 都不是有效括号字符串。解题思路
题目要求将有效括号字符串 seq 拆分成两个不相交的有效括号子序列
观察深度特性: 在原有效括号字符串中,每一个括号都有一个对应的嵌套深度(层级)。若原字符串的最大深度为
,为了让拆分后的 最小,最优的策略是让 和 各自分担一半的嵌套深度,即最大深度约为 。 按奇偶层级平分: 我们可以维护一个表示当前嵌套深度的变量
d(初始为 0):- 遇到左括号
'('时,嵌套深度增加(d++),该左括号所在的深度即为当前深度d; - 遇到右括号
')'时,该右括号与最近未匹配的左括号对应,处于相同的深度d,匹配后嵌套深度减少(d--)。
为了将深度平分,我们只需将处于奇数深度的括号分给其中一组(如 0 或 1),偶数深度的括号分给另一组:
- 遇到
'(':d++,分配标记ans[i] = d % 2; - 遇到
')':分配标记ans[i] = d % 2,然后d--。
这样,相邻嵌套的括号会被交替分配给
和 ,保证了拆分后的两个子序列各自依然是有效括号字符串,且嵌套深度被均匀平分。 - 遇到左括号
C++ 代码实现
class Solution {
public:
vector<int> maxDepthAfterSplit(string seq) {
int n = seq.size();
vector<int> ans(n);
int d = 0; // 当前嵌套深度
for (int i = 0; i < n; ++i) {
if (seq[i] == '(') {
d++;
ans[i] = d % 2; // 奇数层和偶数层分别分配给 1 和 0
} else {
ans[i] = d % 2; // 右括号与对应左括号同层
d--;
}
}
return ans;
}
};复杂度分析
- 时间复杂度:
,只需遍历一次字符串 seq,其中为字符串长度。 - 空间复杂度:
,除了用于存储返回结果的数组外,仅使用了常数级别的额外变量。