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

97 阅读3分钟

问题描述

小R有一个括号字符串 s,他想知道这个字符串是否是有效的。一个括号字符串如果满足以下条件之一,则是有效的:

  1. 它是一个空字符串;
  2. 它可以写成两个有效字符串的连接形式,即 AB
  3. 它可以写成 (A) 的形式,其中 A 是有效字符串。

在每次操作中,小R可以在字符串的任意位置插入一个括号。你需要帮小R计算出,最少需要插入多少个括号才能使括号字符串 s 有效。

例如:当 s = "())" 时,小R需要插入一个左括号使字符串有效,结果为 1

思路解释

这一题的本质上就是括号的配对问题,即每一个左括号都需要配对到一个右括号,或者说遇到每一个右括号之前都应该有一个左括号与之配对。我们可以用计数的方式来设计一种题解,比如从左向右扫描先计算左括号,直到遇到右括号数量-1,然后遇到左括号将多余的部分计入结果,清零从新计算。而我们也可以用堆栈的方式来更直观的看出是哪一些括号没有成功配对。

以下是使用堆栈的实现方式。

def solution(s: str) -> int:
    # write code here
    stack=[]
    for i in s:
        if i =='(':
            stack.append(i)
        elif i==')' :
            if stack :
                if stack[len(stack)-1]=='(':
                    stack.pop()
                elif stack[len(stack)-1]==')':
                    stack.append(i)
            else:
                stack.append(i)
            
    return len(stack)  # placeholder return

首先创建一个用来存储字符的栈用于模拟括号匹配过程中的“压入”与“弹出”操作。

而对于我们遍历字符中所遇到的所有的左括号统统压入栈中,用于等待匹配右括号。毕竟有左括号才能右括号匹配上。

而对于遇到右括号,我们则需要先判断栈顶是什么。

栈顶是左括号,则说明这个左括号是与之配对的,我们将这个左括号出栈。

我们遇到右括号,就说明没有与之配对的左括号,我们就将其压入栈中。

等到程序遍历完字符串,我们就可以得到一个未能匹配上的所有括号的栈,可以将其打印出来,如果需要的话还可以在栈中存储它们的下标,而输出长度就是我们所需要的答案。

复杂度分析

主要操作是遍历字符串,并根据情况压栈或入栈,压栈入栈操作对于每一个字符都只会操作一次,所以时间复杂度是O(n)。而空间复杂度,开辟了一个新的栈用于存储未匹配的括号,栈的大小取决于字符串中左括号和右括号的数量。在最坏的情况下,假如字符串中全部是左括号(例如 "((((("),那么栈中将存储所有的左括号,栈的最大大小为 n(即输入字符串的长度)。在其他情况下,栈的大小会小于 n,因为每对匹配的括号会被弹出栈。 除此基本没有用多的空间,因此空间复杂度也是O(n)。