LeetCode 热题 HOT 100 第七十天 301. 删除无效的括号 困难题 用python3求解

题目地址

给你一个由若干括号和字母组成的字符串s,删除最小数量的无效括号,使得输入的字符串有效。

返回所有可能的结果。答案可以按任意顺序返回。

示例 1:
输入:s = “()())()”
输出:[“(())()”,“()()()”]

示例 2:
输入:s = “(a)())()”
输出:[“(a())()”,“(a)()()”]

示例 3:
输入:s = “)(”
输出:[“”]

提示:
1 <= s.length <= 25
s 由小写英文字母以及括号 ‘(’ 和 ‘)’ 组成
s 中至多含 20 个括号
在这里插入图片描述
解法:BFS

参考:https://leetcode.cn/problems/remove-invalid-parentheses/solution/bfsjian-dan-er-you-xiang-xi-de-pythonjiang-jie-by-/

为何用BFS而不是DFS
利用BFS理解起来要远远比DFS要简单的多,因为这道题说的是删除最少的括号!!,如果我们每次只删除一个括号,然后观察被删除一个括号后是否合法,如果已经合法了,我们就不用继续删除了啊。因此我们并不需要将遍历进行到底,而是层层深入,一旦达到需求,就不再深入了。

如何进行BFS
我们做BFS,上一层level和下一层level之间的关系为:把所有上一层level中的每个元素都拿出来,列举出在删除一个括号后的所有可能的情况。(不管删除以后是否合法),添加到下一个level中的元素。

例如:current level是 [“(()”, “())”]

  • 那么下一层level中的元素应该是:
  1. 对 “(()” 删除一个括号的所有可能为: (), (), ((
  2. 对 “())” 删除一个括号的所有可能为: (), )), ()
    这六个就是下一个level的全部内容了。

如何解决重复的问题
可是我们发现问题,就是有重复的元素出现。
很简单,我们把level中的list换成set,就避免的重复。

如何检查括号是否是个合法括号
如何检查括号是否是一个合法的括号,这是一个简单题,可以用堆栈,也可以维护计数器。

小技巧:
filter(func, param) 可以得到param中所有符合条件的元素
其中判定方法根据func返回的True or False 来决定。

代码实现:

class Solution:
    def removeInvalidParentheses(self, s:str) -> List[str]:
        def isValid(s:str)->bool:
            cnt = 0
            for c in s:
                if c == "(": cnt += 1
                elif c == ")": cnt -= 1
                if cnt < 0: return False  # 只用中途cnt出现了负值,你就要终止循环,已经出现非法字符了
            return cnt == 0

        # BFS
        level = {s}  # 用set避免重复
        while True:
            valid = list(filter(isValid, level))  # 所有合法字符都筛选出来
            if valid: return valid # 如果当前valid是非空的,说明已经有合法的产生了
            # 下一层level
            next_level = set()
            for item in level:
                for i in range(len(item)):
                    if item[i] in "()":                     # 如果item[i]这个char是个括号就删了,如果不是括号就留着
                        next_level.add(item[:i]+item[i+1:])
            level = next_level

以示例二为例:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值