问题描述
小R有一个括号字符串s,他想知道这个字符串是否是有效的。一个括号字符串如果满足以下条件之一,则是有效的!
1.它是一个空字符串;
2.它可以写成两个有效字符串的连接形式,即 AB,3. 它可以写成(A) 的形式,其中 A是有效字符串。在每次操作中,小R可以在字符串的任意位置插入一个括号。你需要帮小R计算出,最少需要插入多少个括号才能使括号字符串s有效,例如:当s="())"时,小R需要插入一个左括号使字符串有效,结果为 1。
测试样例
样例1:
输入:s ="())"输出:1
样例2:
输入:s ="((("输出:3
样例3:
输入:s="()"输出:0
样例4:
输入:s ="()))(("输出:4
解题思路
- 初始化变量:
-
left:用于跟踪未匹配的左括号数量。每当我们遇到一个左括号,这个数量就会增加;每当遇到一个右括号且没有匹配的左括号,这个数量就会减少。to_insert:用于记录需要插入的括号数量。每当我们遇到一个右括号而没有足够的左括号与之匹配时,我们就需要插入一个左括号,并将to_insert加1。
- 遍历字符串:
-
- 对于字符串中的每个字符,如果是左括号
(,我们增加left的计数,因为现在我们有一个未匹配的左括号。 - 如果是右括号
),我们尝试减少left的计数,这意味着我们尝试将这个右括号与一个未匹配的左括号匹配。如果left变为负数,这意味着没有足够的左括号与当前的右括号匹配,因此我们需要插入一个左括号来匹配这个右括号,并将to_insert加1。同时,我们将left重置为0,因为插入的左括号已经与当前的右括号匹配了。
- 对于字符串中的每个字符,如果是左括号
- 处理剩余的左括号:
-
- 遍历结束后,
left中可能还有剩余的未匹配的左括号。对于每个未匹配的左括号,我们需要插入一个右括号来与之匹配,因此我们将to_insert增加left的值。
- 遍历结束后,
- 返回结果:
-
- 最后,
to_insert包含了我们需要插入的括号的总数,这就是使得原始字符串有效的最小插入次数。
- 最后,
示例
示例输入 s = "())" 来说明这个过程:
- 初始化
left = 0和to_insert = 0。 - 遍历字符串:
-
- 遇到第一个右括号
),left = 0 - 1 = -1(没有匹配的左括号,需要插入一个左括号),to_insert = 1。 - 遇到第二个右括号
),left = -1 - 1 = -2(没有匹配的左括号,需要再插入一个左括号),to_insert = 2。
- 遇到第一个右括号
- 遍历结束,
left = -2(有两个未匹配的右括号),这意味着我们需要再插入两个右括号来匹配这两个未匹配的左括号。 - 总的插入次数是
to_insert = 2(为右括号插入的左括号)加上abs(left) = 2(为左括号插入的右括号),所以结果是2 + 2 = 4。
因此,最少需要插入4个括号来使字符串 s = "())" 有效。
代码实现
def solution(s: str) -> int:
left = 0 # 未匹配的左括号数量
to_insert = 0 # 需要插入的括号数量
for char in s:
if char == '(':
left += 1
elif char == ')':
left -= 1
if left < 0:
# 没有匹配的左括号,需要插入一个左括号
to_insert += 1
left = 0 # 插入左括号后,重置未匹配的左括号数量
return to_insert + abs(left) # 未匹配的左括号需要插入右括号
if __name__ == '__main__':
print(solution("())") == 1)
print(solution("(((") == 3)
print(solution("()") == 0)
print(solution("()))((") == 4)