Leetcode 31. 删除无效的括号

在这里插入图片描述

心路历程:

一开始看到有点懵,后来发现有点像按照一定规则穷举所有可能情况,想到了排列组合问题,再结合问题长度不固定,无法用已知个for循环表示,从而想到了回溯。这个题相当于需要在一定规则下枚举。
按照回溯的模板,递归循环是整个字符串s,for循环是候选集合。候选集合为第i个元素 “选” 或者 “不选” ,按照这个思路,其实就已经可以把所有可能组成的情况给遍历到,然后再从所有结果里搜集满足条件的即可。

这道题在回溯问题里很有代表性,考察了很多点,包括怎么对排列问题进行建模(选or不选)、如何判断满足括号条件(栈)、如何剪枝。一开始把问题想简单了,导致写完之后花了很长时间解决未通过的案例,这里面还是有一些细节需要考虑的,比如任何回溯都得在递归函数调用结束后“恢复现场”。

注意的点:

1、回溯算法在记录path时一定要记得copy
2、回溯函数中任何递归调用后都得恢复路径,比如这个问题里遇到字母时,虽然形成的树只有一个分支,但是返回后也得恢复path才行;当时第一次想这个问题以为单分支不用恢复路径导致de了半天bug。还是需要理解回溯是遍历边这个概念。
3、剪枝的判断直接返回就行,把剪枝的部分当作不需要记录path的终止条件即可。
4、每个节点候选集合都有空字符串和括号两个选择,需要遍历,没法贪婪地认为有括号选括号,因为需要考虑所有的组合。
5、注意题目中找的是删除最少括号后的所有可能组合,也就是最长的合法解,并且不能包含重复元素。

感悟:

1、算法题主要考察两类能力:一是对问题进行建模的能力;二是逻辑条件的想全能力。很多时候知道问题大概怎么做,但是具体想各种情况时还是会漏掉一些情况或者想错一些情况。
2、回溯问题debug可以从打印路径和候选集合的角度寻找错误。
3、很多算法中循环的建模思路都可以按照’选‘or’不选‘ 或者 ’选哪个‘的思路考虑,尤其在回溯、递归、动态规划等问题上,可以建模为决策问题。这一点其实和DRL在求解组合优化问题时的两类动作建模思路是一致的。

解法:

这道题有两个思路:思路一:剪枝+选择后序有可能形成最长路径;解法二:剪枝+找到所有的+判断满足条件的最长的。第二个可能更清晰,不过由于刚做完括号的题所以按照第一个思路写的AC解:

class Solution:
    def removeInvalidParentheses(self, s: str) -> List[str]:
        from collections import Counter
        path = []
        res = []
        n = len(s)
        kuohaos = ['(', ')']
        mystack = Mystack()
        maxlen = 0

        def dfs(i):  # i代表遍历字符串的第i个元素
            # nonlocal s, n, res, path, mystack # 这一行可有可无
            nonlocal maxlen  # 这一行必须有

            # 剪枝:把一些不可能更长的去掉;
            if (n - len(path)) + len(''.join(path)) < maxlen:
                return
           
            if i == n:
                string = ''.join(path.copy())
                maxlen = max(maxlen, len(string))
                res.append(string)
                return
            
            if s[i] not in kuohaos:
                path.append(s[i])
                dfs(i+1)
                path.pop()  # 这块也得回溯!!!!!!!
            else:
                candidate = [""]
                # 看第i个括号能不能选即可
                if s[i] == '(':  # 后面)的数量大于等于栈长+1就可以选
                    c = Counter(s[i+1:] + ')')  # +1防止为空
                    # print(mystack.sk, c[')'], mystack.len())
                    if c[')'] - 1 >= mystack.len() + 1: 
                        candidate.append("(")
                elif s[i] == ')':  # 栈里有左括号
                    if mystack.len() > 0:
                        candidate.append(')')
                else:
                    assert False, s[i]
                for each in candidate:
                    # print(each, path, i)
                    path.append(each)  # path 怎么会这么长?
                    # 维护一下栈
                    if each != "":
                        mystack.append(each)
                    dfs(i+1)
                    path.pop()
                    if each != "":
                        mystack.pop(each)
        dfs(0)
        # 返回res里最长的
        lengths = [len(eve) for eve in res]
        res = [eve for eve in res if len(eve) == max(lengths)]
        return list(set(res))  # 需要去重
                        

class Mystack:
    def __init__(self):
        from collections import deque
        self.sk = deque()
    
    def pop(self, ele):
        if ele == '(':
            self.sk.pop()
        elif ele == ')':
            self.sk.append('(')
        else:
            assert False, ele
    
    def append(self, ele):
        if ele == '(':
            self.sk.append('(')
        elif ele == ')':
            assert len(self.sk) != 0
            self.sk.pop()
        else:
            assert False, ele

    def len(self):
        return len(self.sk)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/466703.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

桌面云解决方案

桌面云解决方案是一种基于云计算的服务&#xff0c;它将用户的桌面环境托管在云端&#xff0c;允许用户通过互联网访问自己的虚拟桌面。这种解决方案为企业和个人用户提供了一种灵活、可扩展且成本效益高的桌面计算方式。以下是一些桌面云解决方案的关键特点和优势&#xff1a;…

MusicHiFi: Fast High-Fidelity Stereo Vocoding

文章目录 abstract abstract demo: https://musichifi.github.io/web/主要用于高精度的音乐场景文章主要做了两件事&#xff1a;&#xff08;1&#xff09;低频mel谱输入&#xff0c;生成更高频率的语音&#xff1b;&#xff08;2&#xff09;单声道音频生成立体声&#xff1b…

AI工具快速部署

演示站见文章底部 部署教程 搭建一键整合包&#xff0c;你需要的东西有&#xff1a; 一个最低1h1g的海外服务器 推荐服务器系统为&#xff1a;CentOS-7.9.2111-x64 一份NineAI一件整合包代码 一定的linux指令知识第一步 通过ssh工具连接服务器 同时打开宝塔面板至文件区域 将…

代码随想录算法训练营第二十五天|● 216.组合总和III ● 17.电话号码的字母组合(JS写法)

216 组合总和Ⅲ 题目链接/文章讲解&#xff1a;https://programmercarl.com/0216.%E7%BB%84%E5%90%88%E6%80%BB%E5%92%8CIII.html 视频讲解&#xff1a;https://www.bilibili.com/video/BV1wg411873x 方法一&#xff1a;自己写的 自己写的&#xff0c;本题和77很像&#xf…

连号区间数c++

题目 输入样例1&#xff1a; 4 3 2 4 1输出样例1&#xff1a; 7输入样例2&#xff1a; 5 3 4 2 5 1输出样例2&#xff1a; 9样例解释 第一个用例中&#xff0c;有 77 个连号区间分别是&#xff1a;[1,1],[1,2],[1,3],[1,4],[2,2],[3,3],[4,4][1,1],[1,2],[1,3],[1,4],[2,2…

关于Oracle Primavera P6的各数据库帐号用途

在使用/维护P6时&#xff0c;经常会用到各种不同的P6数据库用户&#xff0c;如在连接配置P6 Professional时用到的公共帐号pubuser&#xff0c;进入后台维护p6配置信息(adminpv)或开发常连接的privuser&#xff0c;亦或是配置BI Report/BUSINESS Intelligence报表套件用到的pxr…

Axure 中继器的Item属性介绍及使用

item.列名 获取数据行中指定列的值。 index 获取索引编号&#xff0c;编号起始值为1 isFirst 判断数据是否为第一行 isLast 判断是否为最后一行 isEven 判断是否为偶数行 isOdd 判断是否为奇数行 isMarked 判断行是否被标记 isVisible 改行是否为显示

8年测试总结,自动化测试必要注意点+自动化测试框架(汇总)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、开始自动化测试…

工具精灵--超级好用的在线工具网站

工具精灵是一个超级好用的在线工具网站&#xff0c;它有这些功能&#xff1a;json格式化、xml格式化、markdown在线编辑、sql格式化、json转Java、xml转Java等。 虽然有很多这种类似的网站了&#xff0c;但它们并不好用&#xff0c;很粗糙。工具精灵超级好用&#xff0c;细节方…

详解Python中的缩进和选择

缩进 Python最具特色的是用缩进来标明成块的代码。我下面以if选择结构来举例。if后面跟随条件&#xff0c;如果条件成立&#xff0c;则执行归属于if的一个代码块。 先看C语言的表达方式&#xff08;注意&#xff0c;这是C&#xff0c;不是Python!&#xff09; if ( i > 0 …

el-upload的多个文件与单个文件上传

样式图&#xff1a; 场景多个&#xff1a; 使用el-upload上传多个文件 <el-upload class"upload-demo" :action"uploadUrl" :on-remove"handleRemove1":on-success"handleAvatarSuccess1" multiple :limit"5" :on-exc…

gma 2.0.7 (2024.03.16) 更新日志

安装 gma 2.0.7 pip install gma2.0.7网盘下载&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1P0nmZUPMJaPEmYgixoL2QQ?pwd1pc8 提取码&#xff1a;1pc8 注意&#xff1a;此版本没有Linux版&#xff01; 编译gma的Linux虚拟机没有时间修复&#xff0c;本期Linux版继…

阿里云服务器1个月收费价格表,5元1个月起

阿里云服务器一个月多少钱&#xff1f;最便宜5元1个月。阿里云轻量应用服务器2核2G3M配置61元一年&#xff0c;折合5元一个月&#xff0c;2核4G服务器30元3个月&#xff0c;2核2G3M带宽服务器99元12个月&#xff0c;轻量应用服务器2核4G4M带宽165元12个月&#xff0c;4核16G服务…

现货白银是伦敦银吗?要看这个因素

在国际贵金属投资市场上&#xff0c;伦敦银就是现货白银交易的别名&#xff0c;但这仅仅是指以“美元/盎司”计价、在全球化的网络进行的正宗国际现货白银交易&#xff0c;一些个别国家和地区的现货白银交易&#xff0c;可不能称为伦敦银交易。 伦敦作为全球金融中心之一&#…

Java微服务分布式事务框架seata

&#x1f339;作者主页&#xff1a;青花锁 &#x1f339;简介&#xff1a;Java领域优质创作者&#x1f3c6;、Java微服务架构公号作者&#x1f604; &#x1f339;简历模板、学习资料、面试题库、技术互助 &#x1f339;文末获取联系方式 &#x1f4dd; 往期热门专栏回顾 专栏…

深度强化深化03 Rewards and Returns

Return Value Function Vpei当前的局势好不好 自动驾shi方向盘的角度

AIGC元年大模型发展现状手册

零、AIGC大模型概览 AIGC大模型在人工智能领域取得了重大突破&#xff0c;涵盖了LLM大模型、多模态大模型、图像生成大模型以及视频生成大模型等四种类型。这些模型不仅拓宽了人工智能的应用范围&#xff0c;也提升了其处理复杂任务的能力。a.) LLM大模型通过深度学习和自然语…

【Python循环3/5】条件循环语句

目录 导入 条件循环 边界条件 while循环 死循环 while循环与for循环的区别 总结 知识图谱 导入 我们已经学习了如何利用for语句实现代码重复执行的循环结构。通过遍历列表&#xff0c;输出其中的每一个元素。 for循环就像是排队办事&#xff0c;一个个进入&#xff0c;轮…

一个注解解决接口耗时日志的打印

在日常开发中&#xff0c;常常需要统计方法的耗时情况&#xff0c;一般的写法是在进入方法之前&#xff0c;记录一下当前时间戳&#xff0c;在方法最后再用当前时间戳减去进入时候的时间戳就是耗时情况&#xff0c;方法很简单&#xff0c;但不够优雅。 接下来我们用一个注解AOP…

吴恩达机器学习笔记 二十四 决策树模型 学习过程 什么时候停止分裂 如何选择结点特征

案例&#xff1a;识别小猫&#xff0c;上面这个分类的特征 x 采用分类值&#xff08;几个离散的值&#xff09; 决策树最顶端的结点称根结点(root node)&#xff0c;除了根结点和叶子结点之外的叫决策结点(decision node)&#xff0c;最底层的叫叶子结点(leaf node)&#xff0c…
最新文章