括号补全问题(青训营X豆包MarsCode) | 豆包MarsCode AI 刷题

69 阅读4分钟

问题描述

小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

要解决这个括号补全问题,我们需要确保字符串中的每个括号都是有效配对的。具体来说,我们要判断给定的字符串中缺少多少个括号,以使其成为一个有效的括号字符串。我们可以采用一种栈的思想来解决这个问题,或者直接用两个计数器来模拟括号的匹配过程。

问题分析

一个有效的括号字符串需要满足以下条件:

  1. 每个左括号(都必须有一个右括号)来与之配对。
  2. 在字符串的过程中,任何时刻左括号的数量不能少于右括号的数量。

思路

我们可以使用两个计数器:

  • left_needed:用于记录当前缺少的左括号数量(即多余的右括号数量)。每当遇到一个右括号,而当前没有对应的左括号时,我们就增加这个计数器。
  • right_needed:用于记录当前缺少的右括号数量(即多余的左括号数量)。每当遇到一个左括号时,我们就增加这个计数器。

具体步骤:

  1. 初始化两个计数器:left_neededright_needed都为 0。
  2. 遍历字符串
    • 如果遇到左括号(,说明需要一个右括号来配对,所以增加right_needed
    • 如果遇到右括号),检查是否有未配对的左括号。如果有,减少right_needed,否则增加left_needed,表示缺少一个左括号。
  1. 最后,left_neededright_needed的总和即为需要补充的括号数量。

代码实现

def minAddToMakeValid(s):
    left_needed = 0  # 记录缺少的左括号
    right_needed = 0  # 记录缺少的右括号
    
    for char in s:
        if char == '(':
            right_needed += 1  # 需要一个右括号来配对
        elif char == ')':
            if right_needed > 0:
                right_needed -= 1  # 找到一个配对的右括号
            else:
                left_needed += 1  # 没有配对的左括号,增加一个左括号
    
    return left_needed + right_needed  # 总共需要补充的括号数

# 测试样例
print(minAddToMakeValid("())"))  # 输出: 1
print(minAddToMakeValid("((("))  # 输出: 3
print(minAddToMakeValid("()"))   # 输出: 0
print(minAddToMakeValid("()))((")) # 输出: 4

解释

  • 样例 1: s = "())"
    • 第一个右括号没有对应的左括号,因此需要一个左括号,left_needed = 1,最终需要补充 1 个括号。
  • 样例 2: s = "((("
    • 有三个左括号,但是没有右括号配对,因此需要 3 个右括号,right_needed = 3,最终需要补充 3 个括号。
  • 样例 3: s = "()"
    • 这个字符串已经是有效的,因此不需要任何补充括号,返回 0。
  • 样例 4: s = "()))(("
    • 在遍历时:
      • 右括号多于左括号,需要 2 个左括号补充。
      • 左括号多于右括号,需要 2 个右括号补充。
    • 总共需要补充 4 个括号。

时间复杂度

  • 时间复杂度O(n),其中 n 是字符串的长度。我们只需要遍历一次字符串,进行常数时间的操作。
  • 空间复杂度O(1),我们只使用了常数空间来存储计数器。

总结

这个问题可以通过模拟括号配对的过程来解决,使用两个计数器分别统计缺少的左括号和右括号。每遍历一次字符串,我们更新这些计数器,最终的结果就是需要插入的最少括号数。