DFS一般用在路径求解问题上,这道题也算是一种变形的路径求解。具体的路径选择就是要不要添加当前的括号。这道题和第85题均是先对当前的数据遍历,进行了一次处理之后再往下做。就相当于把问题分解为两部分了。第一部分先遍历字符串,求出整个字符串中需要删除的左括号数和右括号数,分别存在leftRemove和rightRemove中。第二部分再对字符串进行深度优先搜索DFS,如果遍历到字符串尾后,所有该删除的左括号和右括号都被删除了,那么就说明找到了一条路径,找到了一个解。在DFS时,对是否向路径添加某个符号的过程进行剪枝,剪枝方式看代码中注释。
class Solution:
def removeInvalidParentheses(self, s: str) -> List[str]:
# s为空的特殊情况判断
if not s:
return [""]
l = len(s)
result = set()
# 需要删除的左括号数
leftRemove = 0
# 需要删除的右括号数
rightRemove = 0
for i in range(l):
if s[i] == '(':
leftRemove += 1
elif s[i] == ')':
if leftRemove != 0:
leftRemove -= 1
else:
rightRemove += 1
def dfs(index, leftCount, rightCount, leftRemove, rightRemove, path):
# 结束条件
if index == l:
# 如果该删除的都删除了,且由于不会删多,所以此判断条件下就是答案中的一个字符串路径
if leftRemove == 0 and rightRemove == 0:
result.add(path)
return
c = s[index]
# 添加该符号
if c != '(' and c != ')':
# 如果不是左括号或者右括号,那么直接向路径中加入该字符
dfs(index+1, leftCount, rightCount, leftRemove, rightRemove, path+c)
elif c == '(':
# 如果是左括号,那么直接加
dfs(index+1, leftCount+1, rightCount, leftRemove, rightRemove, path+c)
elif leftCount > rightCount:
# 只有在左括号数多于右括号数时才向字符串中加右括号,剪枝
dfs(index+1, leftCount, rightCount+1, leftRemove, rightRemove, path+c)
# 删除该符号
# 只有在leftRemove和rightRemove不为0时,才删除左、右括号
if c == '(':
if leftRemove != 0:
dfs(index+1, leftCount, rightCount, leftRemove-1, rightRemove, path)
elif c == ')':
if rightRemove != 0:
dfs(index+1, leftCount, rightCount, leftRemove, rightRemove-1, path)
dfs(0, 0, 0, leftRemove, rightRemove, "")
return list(result)