删除无效的括号
考虑到题目要求求出所有最长组合,考虑用暴力搜索尝试每一种情况,并在特定情况进行剪枝。
import copy
class Solution:
def removeInvalidParentheses(self, s):
# 统计给定的字符串中 左括号 和 右括号 的数目 以便在回溯时进行剪枝
# 统计应该删除的 左括号 和 右括号 数目 来计算方法如下:
# 1)当右括号全部计数完成后,剩余的左括号应该全部删除
# 2)当一个右括号出现时 左边没有相应的左括号匹配,应该删除
l_count, l_remove = 0, 0
r_count, r_remove = 0, 0
for i in s:
if i == '(':
l_count += 1
l_remove += 1
elif i == ')':
r_count += 1
if l_remove > 0:
l_remove -= 1
else:
r_remove += 1
n = len(s)
n_comb = n - r_remove - l_remove
# 根据 应该删除的 左右括号的数目 计算出最后答案字符串的长度
max_score = min(l_count, r_count)
# 回溯过程中的最高得分 记遍历到左括号时 +1分, 右括号 -1分
ans = []
def backtracking(idx, cur_comb, l_remove, r_remove, score):
# idx: s中的下标 ;cur_comb:当前扫描字符串长度
# base case
nonlocal max_score
if l_remove < 0 or r_remove < 0 or score < 0 or score > max_score:
return
if len(cur_comb) == n_comb and score == 0:# 同时满足两个条件时 加入答案
ans.append(copy.deepcopy(cur_comb))
if idx == n:# 下标越界 直接返回
return
parenthese = s[idx]
if parenthese == '(':
backtracking(idx + 1, cur_comb, l_remove - 1, r_remove, score)
# 删除当前括号
backtracking(idx + 1, cur_comb + parenthese, l_remove, r_remove, score + 1)
# 保留当前括号
elif parenthese == ')':
backtracking(idx + 1, cur_comb, l_remove, r_remove - 1, score)
# 删除当前括号
backtracking(idx + 1, cur_comb + parenthese, l_remove, r_remove, score - 1)
# 保留当前括号
else:
backtracking(idx + 1, cur_comb + parenthese, l_remove, r_remove, score)
# 其他字符 保留
backtracking(0, "", l_remove, r_remove, 0)
# 从第一个字符DFS
ans = list(set(ans))
# 集合去重
return ans