301. 删除无效的括号

https://leetcode-cn.com/problems/remove-invalid-parentheses/

一、回溯+少量剪枝

首先计算最少删除左右括号数量lremove和rremove,即剪枝减少递归层数:

对字符串每个位置i(i从0~n-1)尝试删除,在递归中带入lremove和rremove,降为0就是递归出口。

class Solution:
    def removeInvalidParentheses(self, s: str):
        res = set()	 #去重
        # 计算最少删除左右括号数量
        lremove, rremove = 0, 0
        for c in s:
            if c == '(':
                lremove += 1
            elif c == ')':
                #左括号数为0时,右括号数加一;否则左括号数减一(抵消)
                if lremove == 0:
                    rremove += 1
                else:
                    lremove -= 1

        # 辅助函数:校验括号是否合法
        def isValid(str):
            cnt = 0
            for c in str:
                if c == '(':
                    cnt += 1
                elif c == ')':
                    cnt -= 1
                    if cnt < 0:
                        return False
            return cnt == 0

        #回溯函数
        #lremove,rremove分别为要删除的左右括号
        def bt(s, start, lremove, rremove):
            if lremove == 0 and rremove == 0:	#递归出口
                if isValid(s):  #括号合法才记录
                    res.add(s)
                return
            for i in range(start, len(s)):        
                 # 如果剩余的字符无法满足去掉的数量要求,直接返回
                if lremove + rremove > len(s) - i:
                    return
  
                # 尝试去掉一个左括号
                if lremove > 0 and s[i] == '(':
                    bt(s[:i] + s[i + 1:], i, lremove - 1, rremove)
                # 尝试去掉一个右括号
                if rremove > 0 and s[i] == ')':
                    bt(s[:i] + s[i + 1:], i, lremove, rremove - 1)

		# 进行回溯
        bt(s, 0, lremove, rremove)
        return list(res)

再优化

再剪枝,去除连续相同的括号的情况,

比如当前遇到的字符串为 "(((())",去掉前四个左括号中的任意一个,生成的字符串是一样的,均为"((())"

还有就是递归过程中,当右括号数量超过左括号时可以直接return(待实现)

最后更新于