题目链接:301. 删除无效的括号
括号合法
栈
- 当遇到左括号时,入栈
- 当遇到右括号时:i. 栈不为空,此时将栈弹出一个左括号意味着与当前的右括号匹配;ii. 栈为空,说明该右括号前面没有一个左括号与之匹配,说明此字符串不合法。
计数
- 左右括号的数量相等
- 前缀中左括号的数量大于右括号
最小数量
从原长度开始一个一个删,当出现第一个合法path之后,比这个path短的都不用看了。
剪枝
- 最小数量的剪枝,
if n - index + len(path) < max_len:
就不要了,要放在第一个if,不然max_len
会被覆盖; - 如果当前处理的是有括号,而st里已经是空的了,这个有括号必不要了;
- 如果左右有一边是空的,也就是说所有括号都得删了,这种情况就直接出字母就行了,不用进去了。
错误
一开始写的时候忘记让他循环起来了,在if里写了第一个backtracking(index+1)
,以为就可以了,但这样只会一路往下走但是不会回头,pop也就没有意义了,回溯就是还原现场然后重新选择,所以一定要让他能重新选(循环下去),所以后面得加一个backtracking(index+1)
。
其实主要是这道题不知道怎么用for循环…结果最后就忘了。
class Solution:
def removeInvalidParentheses(self, s: str) -> List[str]:
path = []
result = set()
st = []
n = len(s)
max_len = -1
def count(s):
l, r = 0,0
d = ''
for i in s:
if i == '(':
l += 1
elif i == ')':
r += 1
else:
d += i
return l,r,d
def backtracking(index):
nonlocal max_len
if n - index + len(path) < max_len:
return
if index == n:
#print(path,st,max_len)
if st == []:
max_len = len(path)
result.add(''.join(path))
return
if s[index] not in '()':
path.append(s[index])
backtracking(index+1)
path.pop()
else:
path.append(s[index])
if s[index] == '(':
st.append(s[index])
backtracking(index+1)
st.pop()
elif s[index] == ')' and st:
st.pop()
backtracking(index+1)
st.append('(')
#elif s[index] == ')' and not st:
#backtracking(index+1)
path.pop()
backtracking(index+1)
l,r,d = count(s)
if l == 0 or r == 0:
return [d]
backtracking(0)
return list(result)