[Java·算法·困难]LeetCode32. 最长有效括号
每天一题,防止痴呆
- 题目
- 示例
- 分析思路1
- 题解1
- 分析思路2
- 题解2
- 分析思路3
- 题解3
👉️ 力扣原文
题目
给你一个只包含 '('
和 ')'
的字符串,找出最长有效(格式正确且连续)括号子串的长度。
示例
输入:s = "(()"
输出:2
解释:最长有效括号子串是 "()"
输入:s = ")()())"
输出:4
解释:最长有效括号子串是 "()()"
输入:s = ""
输出:0
输入:s = "(())("
输出:4
分析思路1
用栈的解法:
- 定义一个栈,用于存储字符在字符串中的下标。初始化时,将-1压入栈中。
- 从字符串的左边开始遍历,如果遇到左括号,则将其下标压入栈中。
- 如果遇到右括号,则弹出栈顶元素,表示与该右括号匹配的左括号已经找到。如果此时栈为空,则将该右括号的下标压入栈中,表示该右括号没有匹配的左括号。
- 如果栈不为空,则计算当前子串的长度,即当前右括号的下标减去栈顶元素的值。如果该子串的长度大于最长子串的长度,则更新最长子串的长度。
题解1
class Solution {public int longestValidParentheses(String s) {int maxLen = 0;Stack<Integer> stack = new Stack<>();stack.push(-1);//有效括号长度为当前右括号下标减去栈底元素,初始化要是-1才对for (int i=0; i<s.length(); i++){char c = s.charAt(i);if(c == '('){stack.push(i);}else {stack.pop();//弹出栈顶if(stack.isEmpty()){ // 栈为空,说明当前右括号没有与之匹配的左括号stack.push(i);// 将当前右括号下标压入栈中}else {// 栈不为空,计算有效括号长度int len = i - stack.peek();maxLen = Math.max(maxLen, len);}}}return maxLen;}}
执行结果
分析思路2
双指针:
在此方法中,我们利用两个计数器 left 和 right 。首先,我们从左到右遍历字符串,对于遇到的每个 ‘(’,我们增加 left 计数器,对于遇到的每个 ‘)’ ,我们增加 right 计数器。每当 left 计数器与 right 计数器相等时,我们计算当前有效字符串的长度,并且记录目前为止找到的最长子字符串。当 right 计数器比 left 计数器大时,我们将 left 和 right 计数器同时变回 0。
这样的做法贪心地考虑了以当前字符下标结尾的有效括号长度,每次当右括号数量多于左括号数量的时候之前的字符我们都扔掉不再考虑,重新从下一个字符开始计算,但这样会漏掉一种情况,就是遍历的时候左括号的数量始终大于右括号的数量,即 (() ,这种时候最长有效括号是求不出来的。
解决的方法也很简单,我们只需要从右往左遍历用类似的方法计算即可,只是这个时候判断条件反了过来:
当left 计数器比right 计数器大时,我们将left 和 right 计数器同时变回 0
当 left 计数器与 right 计数器相等时,我们计算当前有效字符串的长度,并且记录目前为止找到的最长子字符串
这样我们就能涵盖所有情况从而求解出答案。
题解2
class Solution {public int longestValidParentheses(String s) {int left=0,right=0,maxLen=0;for (int i = 0; i < s.length(); i++) {if(s.charAt(i)=='('){left++;}else {right++;}if(left == right){maxLen = Math.max(maxLen, right*2);}else if(right > left){left = right = 0;}}left = right = 0;for (int i = s.length()-1; i >= 0 ; i--) {if(s.charAt(i)=='('){left++;}else {right++;}if(left == right){maxLen = Math.max(maxLen, right*2);}else if(left > right){left = right = 0;}}return maxLen;}}
执行结果
分析思路3
使用动态规划:
我们定义一个一维数组 dp,其中 dp[i] 表示以 i 位置结尾的有效括号子串的最长长度。在计算 dp[i] 时,我们需要根据 s[i] 的值进行分类讨论:
1.当 s[i] 为左括号 ‘(’ 时,以 i 位置结尾的子串肯定不是有效括号子串,因此 dp[i] = 0。
2.当 s[i] 为右括号 ‘)’ 时,我们需要找到与其匹配的左括号。具体来说,我们可以先计算前面已经形成的有效括号长度 preLen,然后在 i - preLen - 1 的位置寻找与当前的右括号相匹配的左括号,即 s[pre]。如果 s[pre] 为左括号,则当前的右括号可以与其闭合,有效长度增加2。此时,我们还需要再往前看一眼,是否还有有效长度,如果有,合并过来。例如:“()(()())” 当前在计算最后一个位置时,dp[7] 已经等于 dp[6]+2 = 4+2,但需要再往前看一眼,dp[1] 还有有效长度,合并过来 dp[7] = 4+2+2。那是否还需要再往前看?不需要了,因为,如果前面还有有效长度,其长度肯定已经合并到 dp[2] 上了。因此,每次只需要再往前多看一眼就可以。
最终答案是 dp 数组中的最大值。
题解3
class Solution {// 子串问题:严格以每个结尾计算个答案,最终答案必在其中public static int longestValidParentheses(String s) {if (s == null || s.length() < 2) return 0;int[] dp = new int[s.length()]; // dp[i]:严格以i位置结尾,形成的有效括号子串最长长度是多少int max = 0; // 最终的答案// dp[0] = 0; // 默认for (int i = 1; i < s.length(); i++) {// if (s.charAt(i) == '(') dp[i] = 0; 以左括号结尾,无效if (s.charAt(i) == ')') {int preLen = dp[i - 1]; // 前面已经形成的有效括号长度int pre = i - 1 - preLen; // 寻找与当前的右括号相匹配的左括号位置:前面有效括号长度再往前一个位置if (pre >= 0 && s.charAt(pre) == '(') { // 如果寻找到左括号:前面有效括号长度再往前一个位置是左括号dp[i] = dp[i-1] + 2; // 可以与当前的右括号闭合,有效长度增加2// 【注意】此时,需要再往前看下,是否还有有效长度,如果有,合并过来// 例如:"()(()())" 当前在计算最后一个位置时,dp[7]已经等于 dp[6]+2 = 4+2// 但需要再往前看一眼,dp[1]还有有效长度,合并过来 dp[7] = 4+2+2// 那是否还需要再往前看?// 不需要了,因为,如果前面还有有效长度,其长度肯定已经合并到dp[2]上了// 因此,每次只需要再往前多看一眼就可以if (pre-1 >= 0) {dp[i] += dp[pre-1];}}max = Math.max(max, dp[i]); // 严格以每个结尾抓一个答案,最终答案必在其中}}return max;}}
执行结果
相关文章:

[Java·算法·困难]LeetCode32. 最长有效括号
每天一题,防止痴呆题目示例分析思路1题解1分析思路2题解2分析思路3题解3👉️ 力扣原文 题目 给你一个只包含 ( 和 ) 的字符串,找出最长有效(格式正确且连续)括号子串的长度。 示例 输入:s "(()&q…...
pytorch如何搭建一个最简单的模型,
一、搭建模型的步骤 在 PyTorch 中,可以使用 torch.nn 模块来搭建深度学习模型。具体步骤如下: 定义一个继承自 torch.nn.Module 的类,这个类将作为我们自己定义的模型。 在类的构造函数 __init__() 中定义网络的各个层和参数。可以使用 to…...

JS实现css的hover效果,兼容移动端
Hi I’m Shendi JS实现css的hover效果,兼容移动端 功能概述 CSS的hover即触碰时触发,在电脑端鼠标触碰,移动端手指触摸 有的时候光靠css实现不了一些效果,例如元素触发hover,其他元素触发动画效果,所以需要…...

企业微信的后台怎么进入和管理?
企业微信管理后台,只有企业的管理员才可以进企业微信后台,普通员工想要进入后台、可以联系管理员将你设置为后台管理员。 一、怎么进入企业微信后台 管理员进入企业微信后台有两种路径; 路径一: 企业管理员直接在浏览器搜索企…...

【2223sW2】LOG2
写在前面 好好学习,走出宿舍,走向毕设! 一些心路历程记录,很少有代码出现 因为鬼知道哪条代码到时候变成毕设的一部分了咧,还是不要给自己的查重挖坑罢了 23.3.2 检验FFT 早上师兄帮忙看了一眼我画的丑图ÿ…...

buuctf-web-[SUCTF 2018]MultiSQL1
打开界面,全部点击一遍,只有注册和登录功能可以使用注册一个账号,注册admin提示用户存在,可能有二次注入,注册admin自动加了一个字符,无法二次注入,点击其他功能点换浏览器重新登录后࿰…...

GitLab创建仓库分配权限
文章目录创建仓库分配权限参考资料创建仓库 点击“New project”创建新项目 分配权限 点击左侧菜单栏“Members”成员,菜单 “Invite member”邀请成员,添加人员;“Invite group”邀请组织,添加一个组织所有成员下面输入框搜索…...

代码随想录-51-110.平衡二叉树
目录前言题目1.求高度和深度的区别节点的高度节点的深度2. 本题思路分析:3. 算法实现4. pop函数的算法复杂度5. 算法坑点前言 在本科毕设结束后,我开始刷卡哥的“代码随想录”,每天一节。自己的总结笔记均会放在“算法刷题-代码随想录”该专…...

项目实战典型案例27——对生产环境以及生产数据的敬畏之心
对生产环境以及生产数据的敬畏之心一:背景介绍总结升华一:背景介绍 本篇博客是对项目开发中出现的对生产环境以及生产数据的敬畏之心行的总结并进行的改进。目的是将经历转变为自己的经验。通过博客的方式分享给大家,大家一起共同进步和提高…...

如何查找你的IP地址?通过IP地址能直接定位到你家!
我们ip地址分为A、B、C、D、E共5类,每一类地址范围不同,从A到Eip地址范围依次递减,其中哦,D和E是保留地址,我们用不了。A、B、C3类地址很多都被美国这样的西方国家分走了,而留给我们的就剩有限的地址了&…...

Containers--array类
Array 类 简介 Array 类是一个固定大小的数组,它的大小在编译时就已经确定了。Array 类的大小是固定的,因此它的大小不能改变。 数组是固定大小的序列容器:它们以严格的线性顺序保存特定数量的元素。 在内部,数组除了包含的元素之外不保留…...

LinqConnect兼容性并支持Visual Studio 2022版本
LinqConnect兼容性并支持Visual Studio 2022版本 现在支持Microsoft Visual Studio 2022版本17.5预览版。 添加了Microsoft.NET 7兼容性。 共享代码-共享相同的代码,以便在不同的平台上处理数据。LinqConnect是一种数据库连接解决方案,适用于不同的基于.…...

流量监管与整形
流量监管与整形概览流量监管介绍流量监管令牌桶流量监管的具体实现单桶单速流量监管双桶单速流量监管双桶双速流量监管流量整形介绍GTS(Generic Traffic Shaping)LR(Line Rate)流量整形与流量监管的区别概览 流量整形是对报文的速…...
详解init 容器
什么是init容器 init 容器是一种特殊容器,在 Pod 内的应用容器启动之前运行。Init 容器可以包括一些应用镜像中不存在的实用工具和安装脚本。 你可以在 Pod 的规约中与用来描述应用容器的 containers 数组平行的位置指定 Init 容器 每个 Pod 中可以包含多个容器&…...
RequestResponseBodyMethodProcessor
既是一个参数解析器,也是一个返回结果处理器。 1.持有消息转换器的集合 protected final List<HttpMessageConverter<?>> messageConverters;2.作为参数解析器,例如对RequestBody标识的参数进行解析 判断是否支持当前类型的参数 Overrid…...

函数的极限
目录 函数的极限 函数极限的定义: 例题: 左右极限: 自变量趋于无穷大时函数的极限: 例题: 函数极限的性质: 函数极限与数列极限之间的关系: 函数的极限 函数极限的定义: 一句…...
dnf命令使用
1. 简介 DNF是新一代的rpm软件包管理器。他首先出现在 Fedora 18 这个发行版中。而最近,它取代了yum,正式成为 Fedora 22 的包管理器 DNF包管理器克服了YUM包管理器的一些瓶颈,提升了包括用户体验,内存占用,依赖分析…...

CLIP CLAP
文章目录CLIPabstractintroCLAP: LEARNING AUDIO CONCEPTS FROM NATURAL LANGUAGE SUPERVISIONabstractmethodCLIP open AI2021.2代码&预训练模型 abstract 原有的基于有监督数据训练的计算机分类任务,在面对新的分类目标时泛化性和可用性都会变差࿱…...
Debezium报错处理系列之五十二:解决Sql Server数据库安装后修改主机名导致sqlserver数据库实例名称没有修改从而无法设置CDC的问题
Debezium报错处理系列之五十二:解决Sql Server数据库安装后修改主机名导致sqlserver数据库实例名称没有修改从而无法设置CDC的问题 一、完整报错二、错误原因三、解决方法Debezium报错处理系列一:The db history topic is missing. Debezium报错处理系列二:Make sure that t…...

scratch老鹰捉小鸡 电子学会图形化编程scratch等级考试二级真题和答案解析2022年12月
目录 scratch老鹰捉小鸡 一、题目要求 1、准备工作 2、功能实现 二、案例分析 <...

css实现圆环展示百分比,根据值动态展示所占比例
代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...
ubuntu搭建nfs服务centos挂载访问
在Ubuntu上设置NFS服务器 在Ubuntu上,你可以使用apt包管理器来安装NFS服务器。打开终端并运行: sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享,例如/shared: sudo mkdir /shared sud…...
React Native 开发环境搭建(全平台详解)
React Native 开发环境搭建(全平台详解) 在开始使用 React Native 开发移动应用之前,正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南,涵盖 macOS 和 Windows 平台的配置步骤,如何在 Android 和 iOS…...
Admin.Net中的消息通信SignalR解释
定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...

【第二十一章 SDIO接口(SDIO)】
第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...
反射获取方法和属性
Java反射获取方法 在Java中,反射(Reflection)是一种强大的机制,允许程序在运行时访问和操作类的内部属性和方法。通过反射,可以动态地创建对象、调用方法、改变属性值,这在很多Java框架中如Spring和Hiberna…...

C++ 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...
数据库分批入库
今天在工作中,遇到一个问题,就是分批查询的时候,由于批次过大导致出现了一些问题,一下是问题描述和解决方案: 示例: // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...

项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)
Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败,具体原因是客户端发送了密码认证请求,但Redis服务器未设置密码 1.为Redis设置密码(匹配客户端配置) 步骤: 1).修…...
安卓基础(aar)
重新设置java21的环境,临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的: MyApp/ ├── app/ …...