小杰的学习过程之1111.有效括号的镶嵌深度

题目转自LeetCode
本人作为算法初学者,来记录对LeetCode题目的思考。其思想主要参照官方解法和网友的方法。

题目叙述

有效括号字符串 定义:对于每个左括号,都能找到与之对应的右括号,反之亦然。详情参见题末「有效括号字符串」部分。

嵌套深度 depth 定义:即有效括号字符串嵌套的层数,depth(A) 表示有效括号字符串 A 的嵌套深度。详情参见题末「嵌套深度」部分。

有效括号字符串类型与对应的嵌套深度计算方法如下图所示:

在这里插入图片描述

给你一个「有效括号字符串」 seq,请你将其分成两个不相交的有效括号字符串,A 和 B,并使这两个字符串的深度最小。

不相交:每个 seq[i] 只能分给 A 和 B 二者中的一个,不能既属于 A 也属于 B 。
A 或 B 中的元素在原字符串中可以不连续。
A.length + B.length = seq.length
深度最小:max(depth(A), depth(B)) 的可能取值最小。 

划分方案用一个长度为 seq.length 的答案数组 answer 表示,编码规则如下:

answer[i] = 0,seq[i] 分给 A 。
answer[i] = 1,seq[i] 分给 B 。

如果存在多个满足要求的答案,只需返回其中任意 一个 即可。

示例 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,而 “)(” 和 “(()” 都不是有效括号字符串。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/maximum-nesting-depth-of-two-valid-parentheses-strings

题解

1.栈

seq = "(()())"
ans = []
d = 0
for c in seq:
    if c == '(':
        d += 1
        ans.append(d % 2)
    if c == ')':
        ans.append(d % 2)
        d -= 1
print(ans)

输出结果:

[1, 0, 0, 0, 0, 1]

此题解参考官方题解
思想就是用一个变量来模拟记录栈的大小,用变量d来记录栈的深度。遍历字符串,当前字符为“(”时压入栈,当前字符为“)”时弹出一个“(”。变量d记录的就是“(”的个数。这时我们利用“(”深度的奇偶性,将他们平均分别分成两组(即:d % 2)。

2.连续两个((或))分在不同组

seq = "(()())"
ans = [1]
for i in range(1, len(seq)):
    ans.append(1 - ans[i - 1]) if seq[i] == seq[i - 1] else ans.append(ans[i - 1])
print(ans)

输出结果:

[1, 0, 0, 0, 0, 1]

通过对方法一的思考,我们得之,只要不将连续两个((或))分在同一组即可,所以有了此方法。
开始我们将第一个“(”分到奇数组(即:ans = [1]),然后用循环判断第二个与第一个是否相同,如果相同,则将他分入另一组(即:append(1 - ans[i - 1])),如果不同,则将他与前面相同的组(即:append(ans[i - 1]))。

3.简化解法1

seq = "(()())"
ans = []
for i, c in enumerate(seq):
    ans.append((i & 1) ^ (c == '('))
print(ans)

输出结果:

[1, 0, 0, 0, 0, 1]

方法一的简化
(i & 1) ^ (c == ‘(’),符号“^”两边不同时返回1,否则返回0。
因为是有效括号,那么他们的编号奇偶性一定不同,即i & 1一定不同。然后利用c是否为 ‘(’,他们的c == '('也一定不同,所以最后他们的(i & 1) ^ (c == ‘(’)值一定同为0或1,达到了分在同一组的目的。

发布了10 篇原创文章 · 获赞 0 · 访问量 50

猜你喜欢

转载自blog.csdn.net/z55947810/article/details/105584995