括号补全问题 | 豆包MarsCode AI刷题

79 阅读2分钟

括号补全问题

一、问题重现

问题描述

小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. 初始化

    • res 用于记录需要插入的括号数量,初始值为 0
    • st 是一个栈,用于存储左括号 (
  2. 遍历字符串

    • 使用 for 循环遍历字符串 s 中的每一个字符。
  3. 处理左括号 (

    • 如果当前字符是左括号 (,将其压入栈 st 中。
  4. 处理右括号 )

    • 如果当前字符是右括号 ),首先检查栈是否为空:

      • 如果栈为空,说明需要插入一个左括号来匹配这个右括号,因此 res 增加 1,并跳过当前循环。

      • 如果栈不为空,检查栈顶元素是否是左括号 (

        • 如果是左括号 (,弹出栈顶元素(匹配成功)。

        • 如果不是左括号 (,弹出栈顶元素,并进一步检查栈是否为空:

          • 如果栈为空,res 增加 1
          • 如果栈不为空,再次弹出栈顶元素。
  5. 处理其他字符

    • 如果当前字符既不是左括号 ( 也不是右括号 ),检查栈是否为空:

      • 如果栈为空,将当前字符压入栈中。
      • 如果栈不为空且栈顶元素不是左括号 (,弹出栈顶元素。
  6. 剩余括号处理

    • 遍历完字符串后,栈中剩余的左括号需要相应数量的右括号来匹配,因此将栈的大小加到 res 上。
  7. 返回结果

    • 返回 res,即最少需要插入的括号数量。

三、代码实现

int solution(const std::string &s) {
  int res = 0;
  stack<char> st;
  for (char c : s) {
    if (c == '(') {
      st.push(c);
    } else if (c == ')') {
      if (!st.empty() && st.top() == '(') {
        st.pop();
      } else {
        res++;
      }
    }
  }
  res += st.size();
  return res;
}

四、算法复杂度分析

  • 时间复杂度O(n),其中 n 是字符串 s 的长度。我们只需要遍历字符串一次。
  • 空间复杂度O(n),在最坏情况下,栈 st 可能存储所有字符。