1. 问题描述:
给你一个由 '('、')' 和小写字母组成的字符串 s。
你需要从字符串中删除最少数目的 '(' 或者 ')' (可以删除任意位置的括号),使得剩下的「括号字符串」有效。
请返回任意一个合法字符串。
有效「括号字符串」应当符合以下 任意一条 要求:
空字符串或只包含小写字母的字符串
可以被写作 AB(A 连接 B)的字符串,其中 A 和 和 B 都是有效「括号字符串」可以被写作 (A) 的字符串,其中 A 是一个有效的「括号字符串」
示例 1:
输入:s = "lee(t(c)o)de)"
输出:"lee(t(c)o)de"
解释:"lee(t(co)de)" , "lee(t(c)ode)" 也是一个可行答案。
示例 2:
输入:s = "a)b(c)d"
输出:"ab(c)d"
示例 3:
输入:s = "))(("
输出:""
解释:空字符串也是有效的
示例 4:
输入:s = "(a(b(c)d)"
输出:"a(b(c)d)"
提示:
1 <= s.length <= 10^5
s[i]
可能是'('
、')'
或英文小写字母
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/minimum-remove-to-make-valid-parentheses
2. 思路分析:
① 括号匹配经常需要使用到栈,这道题目也是一样需要使用到栈的辅助作用来解决,因为使用的是python语言,在python语言中可以使用列表来模拟栈的操作,列表的功能与栈的功能是一样的,一开始的时候想到先扫描一遍给出的字符串s,使用列表记录最后保留的是哪些括号,最后遍历再遍历一遍字符串s将保留的字符加入到结果集中,但是提交上去超时了
② 在官方提供的思路中也是使用栈来进行解决的,思路是使用列表来做括号匹配,使用一个列表来记录需要删除的括号对应的下表的列表,假如是左括号那么进栈,遇到右括号但是记录的列表为空那么说明需要将这个右括号删除,假如栈不为空那么直接弹出左括号,最后再遍历一遍字符串s将不需要删除的字符加入到结果集中即可
③ 需要注意以下几个python常用的方法
1)union方法:union() 方法返回两个集合的并集,即包含了所有集合的元素,重复的元素只会出现一次
x = {"apple", "banana", "cherry"} y = {"google", "runoob", "apple"} z = x.union(y)
输出结果为:
{'cherry', 'runoob', 'google', 'banana', 'apple'}
2)python中的列表相当于栈了,可以弹出栈顶与栈底的元素
3)在python中 None, False, 空字符串"", 0, 空列表[], 空字典{}, 空元组()都相当于False
3. 代码如下:
官方的代码:
class Solution:
def minRemoveToMakeValid(self, s: str) -> str:
indexes_to_remove = set()
stack = []
for i, c in enumerate(s):
if c not in "()":
continue
if c == "(":
stack.append(i)
# 在python中 None, False, 空字符串"", 0, 空列表[], 空字典{}, 空元组()都相当于False
elif not stack:
indexes_to_remove.add(i)
else:
stack.pop()
print(indexes_to_remove, stack)
indexes_to_remove = indexes_to_remove.union(set(stack))
string_builder = []
for i, c in enumerate(s):
if i not in indexes_to_remove:
string_builder.append(c)
# 拼接字符串
return "".join(string_builder)
我一开始的时候写的:
class Solution:
def minRemoveToMakeValid(self, s: str) -> str:
# 一个比较容易想到的方法是统计当前左右括号的数目
res = ""
# 列表就相当于一个栈
leftstack, rightstack = [], []
for i in range(len(s)):
if s[i] == '(':
leftstack.append(i)
elif s[i] == ')':
rightstack.append(i)
leftindex, rightindex = len(leftstack) - 1, len(rightstack) - 1
while leftindex >= 0 and rightindex >= 0:
# 为了避免出现这样的情况l)(ee(e)所以在删除的时候需要加上一个限制条件就是右括号与的下表是
# 一定大于左括号的下表的
if leftstack[leftindex] < rightstack[rightindex]:
# leftstack.pop()
# rightstack.pop()
leftindex -= 1
rightindex -= 1
# 需要加上这样的限制因为可能出现这样的str: "())()((("
else:
leftindex -= 1
leftstack.pop()
while len(rightstack) > len(leftstack) and len(rightstack) > 0:
# 注意应应该是从前面开始删除
rightstack.pop(0)
rightindex -= 1
while len(leftstack) > len(rightstack) and len(leftstack) > 0:
leftstack.pop(0)
leftindex -= 1
for i in range(len(s)):
if s[i] == '(' or s[i] == ')':
if i in leftstack or i in rightstack:
res += s[i]
else: res += s[i]
return res