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