LeetCode_32_困难_最长有效括号

文章目录

  • 1. 题目
  • 2. 思路及代码实现详解(Java)
    • 2.1 动态规划
    • 2.2 不需要额外空间的算法


1. 题目

给你一个只包含 '('')' 的字符串,找出最长有效(格式正确且连续)括号 子串 的长度。

示例 1:

输入: s = s = s= "(()"
输出: 2 2 2
解释:最长有效括号子串是 "()"

示例 2:

输入: s = s = s= ")()())"
输出: 4 4 4
解释:最长有效括号子串是 "()()"

示例 3:

输入: s = s = s= ""
输出: 0 0 0


提示

  • 0 < = s . l e n g t h < = 3 × 1 0 4 0 <= s.length <= 3 \times 10^4 0<=s.length<=3×104
  • s [ i ] s[i] s[i]'('')'

2. 思路及代码实现详解(Java)

2.1 动态规划

我们定义 dp [ i ] \textit{dp}[i] dp[i] 表示以下标 i i i 字符结尾的最长有效括号的长度。我们将 dp \textit{dp} dp 数组全部初始化为 0 0 0 。显然有效的子串一定以 ‘)’ \text{‘)’} ‘)’ 结尾,因此我们可以知道以 ‘(’ \text{‘(’} ‘(’ 结尾的子串对应的 dp \textit{dp} dp 值必定为 0 0 0 ,我们只需要求解 ‘)’ \text{‘)’} ‘)’ dp \textit{dp} dp 数组中对应位置的值,返回其中最大的值即为所求。

我们从前往后遍历字符串求解 dp \textit{dp} dp 值,我们每两个字符检查一次:

  • s [ i ] = ‘)’ s[i] = \text{‘)’} s[i]=‘)’ s [ i − 1 ] = ‘(’ s[i - 1] = \text{‘(’} s[i1]=‘(’,也就是字符串形如 “ … … ( ) ”“ … … ( ) ”“ … … ( ) ” “……()”“……()”“……()” ……()”“……()”“……(),我们可以推出:

dp [ i ] = dp [ i − 2 ] + 2 \textit{dp}[i]=\textit{dp}[i-2]+2 dp[i]=dp[i2]+2

我们可以进行这样的转移,是因为结束部分的 “()” 是一个有效子字符串,并且将之前有效子字符串的长度增加了 2 2 2

  • s [ i ] = ‘)’ s[i] = \text{‘)’} s[i]=‘)’ s [ i − 1 ] = ‘)’ s[i - 1] = \text{‘)’} s[i1]=‘)’,也就是字符串形如 “ … … ) ) ”“ … … ) ) ”“ … … ) ) ” “……))”“……))”“……))” ……))”“……))”“……)),我们可以推出:
    如果有 s [ i − dp [ i − 1 ] − 1 ] = ‘(’ s[i - \textit{dp}[i - 1] - 1] = \text{‘(’} s[idp[i1]1]=‘(’,那么意味着 s [ i ] s[i] s[i] 与之对应,因此得到:

dp [ i ] = dp [ i − 1 ] + dp [ i − dp [ i − 1 ] − 2 ] + 2 \textit{dp}[i]=\textit{dp}[i-1]+\textit{dp}[i-\textit{dp}[i-1]-2]+2 dp[i]=dp[i1]+dp[idp[i1]2]+2

具体分析,我们考虑如果倒数第二个 ‘)’ \text{‘)’} ‘)’ 是一个有效子字符串的一部分(记作 s u b s sub_s subs),对于最后一个 ‘)’ \text{‘)’} ‘)’ ,如果它是一个更长子字符串的一部分,那么它一定有一个对应的 ‘(’ \text{‘(’} ‘(’ ,且它的位置在倒数第二个 ‘)’ \text{‘)’} ‘)’ 所在的有效子字符串的前面(也就是 s u b s sub_s subs 的前面)。因此,如果子字符串 s u b s sub_s subs 的前面恰好是 ‘(’ \text{‘(’} ‘(’ ,那么我们就用 2 2 2 加上 s u b s sub_s subs 的长度( dp [ i − 1 ] \textit{dp}[i-1] dp[i1])去更新 dp [ i ] \textit{dp}[i] dp[i]。同时,我们也会把有效子串 “ ( s u b s ) ” “(sub_s)” (subs) 之前的有效子串的长度也加上,也就是再加上 dp [ i − dp [ i − 1 ] − 2 ] \textit{dp}[i-\textit{dp}[i-1]-2] dp[idp[i1]2]

最后的答案即为 dp \textit{dp} dp 数组中的最大值。该算法的时间复杂度为 O ( n ) O(n) O(n),其中 n n n 是字符串的长度,而空间开销主要是存储 d p dp dp 数组,为 O ( n ) O(n) O(n)

class Solution {public int longestValidParentheses(String s) {int maxans = 0;int[] dp = new int[s.length()];for (int i = 1; i < s.length(); i++) {if (s.charAt(i) == ')') {if (s.charAt(i - 1) == '(') {dp[i] = (i >= 2 ? dp[i - 2] : 0) + 2;} else if (i - dp[i - 1] > 0 && s.charAt(i - dp[i - 1] - 1) == '(') {dp[i] = dp[i - 1] + ((i - dp[i - 1]) >= 2 ? dp[i - dp[i - 1] - 2] : 0) + 2;}maxans = Math.max(maxans, dp[i]);}}return maxans;}
}

执行用时:1 ms
消耗内存:41.28 MB

2.2 不需要额外空间的算法

在此方法中,我们利用两个计数器 left \textit{left} left right \textit{right} right 。首先,我们从左到右遍历字符串,对于遇到的每个 ‘(’ \text{‘(’} ‘(’,我们增加 left \textit{left} left 计数器,对于遇到的每个 ‘)’ \text{‘)’} ‘)’ ,我们增加 right \textit{right} right 计数器。每当 left \textit{left} left 计数器与 right \textit{right} right 计数器相等时,我们计算当前有效字符串的长度,并且记录目前为止找到的最长子字符串。当 right \textit{right} right 计数器比 left \textit{left} left 计数器大时,我们将 left \textit{left} left right \textit{right} right 计数器同时变回 0 0 0

这样的做法贪心地考虑了以当前字符下标结尾的有效括号长度,每次当右括号数量多于左括号数量的时候之前的字符我们都扔掉不再考虑,重新从下一个字符开始计算,但这样会漏掉一种情况,就是遍历的时候左括号的数量始终大于右括号的数量,即 ( ( ) (() (() ,这种时候最长有效括号是求不出来的。

解决的方法也很简单,我们只需要从右往左遍历用类似的方法计算即可,只是这个时候判断条件反了过来:

  • left \textit{left} left 计数器比 right \textit{right} right 计数器大时,我们将 left \textit{left} left right \textit{right} right 计数器同时变回 0 0 0
  • left \textit{left} left 计数器与 right \textit{right} right 计数器相等时,我们计算当前有效字符串的长度,并且记录目前为止找到的最长子字符串

这样我们就能涵盖所有情况从而求解出答案。

class Solution {public int longestValidParentheses(String s) {int left = 0, right = 0, maxlength = 0;for (int i = 0; i < s.length(); i++) {if (s.charAt(i) == '(') {left++;} else {right++;}if (left == right) {maxlength = Math.max(maxlength, 2 * right);} 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) {maxlength = Math.max(maxlength, 2 * left);} else if (left > right) {left = right = 0;}}return maxlength;}
}

执行用时:1 ms
消耗内存:41.16 MB

题解来源:力扣官方题解

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Oracle Data Guard常用命令

--查询数据库角色和保护模式 select database_role,switchover_status from v$database; --切换备库为主库&#xff08;切换后&#xff0c;主库为mount状态&#xff09; --TO PRIMARY alter database commit to switchover to primary; --SESSIONS ACTIVE alter database comm…

springcloud+nacos服务注册与发现

快速开始 | Spring Cloud Alibaba 参考官方快速开始教程写的&#xff0c;主要注意引用的包是否正确。 这里是用的2022.0.0.0-RC2版本的springCloud&#xff0c;所以需要安装jdk21&#xff0c;参考上一个文章自行安装。 nacos-config实现配置中心功能-CSDN博客 将nacos-conf…

Head First Design Patterns -模板方法模式

什么是模板方法模式 在一个方法中定义一个算法的骨架&#xff0c;而把一些步骤延迟到子类。模板方法使得子类可以在不改变算法结构的情况下&#xff0c;重新定义算法的某些步骤。 这些算法步骤中的一个或者多个被定义为抽象的&#xff0c;由子类实现。 类图 代码 书中用泡茶和…

C# 编程语言中访问修饰符(access modifiers)

C#访问修饰符 protected 访问修饰符&#xff1a;1. public 访问修饰符&#xff1a;2. private 访问修饰符&#xff1a;3. internal 访问修饰符&#xff1a;4. protected internal 访问修饰符&#xff1a; 在 C# 编程语言中&#xff0c;有多个访问修饰符&#xff08;access modi…

kotlin中使用myibatis-plus的lambdaQuery的问题

kotlin中使用myibatis-plus的lambdaQuery的问题 代码&#xff1a;lambdaQuery().eq(User::username, username).one()报错&#xff1a;org.apache.ibatis.reflection.ReflectionException: Error parsing property name register$lambda$0. Didnt start with is, get or set.解…

#Linux(Samba安装)

&#xff08;一&#xff09;发行版&#xff1a;Ubuntu16.04.7 &#xff08;二&#xff09;记录&#xff1a; &#xff08;1&#xff09;键入命令安装Samba sudo apt-get install samba &#xff08;2&#xff09;修改samba配置文件 //打开配置文件 sudo vi /etc/samba/smb.…

Java基础-常用类

文章目录 1.Math类2.System类1.exit代码 结果2.arraycopy参数解释代码结果 3.currentTimeMillens代码结果 3.大数处理方案基本介绍BigInteger类介绍代码结果 BigDecimal类介绍代码结果 4.日期类对于IDEA类图中的属性![image-20240101190844530](https://img-blog.csdnimg.cn/im…

HJ10 字符个数统计HJ11 数字颠倒HJ12 字符串反转

HJ10 字符个数统计 字符个数统计_牛客题霸_牛客网 题目分析 这个问题可以通过维护一个字符出现频率的数组来解决。考虑到 ASCII 码的范围是 0~127&#xff0c;我们可以创建一个长度为 128 的布尔数组&#xff08;或者使用位操作优化空间&#xff09;&#xff0c;用来标记某个…

深度学习,CRNN+CTC和Attention OCR你更青睐哪一种?

深度学习在OCR领域的应用已经取得了瞩目的成果&#xff0c;而选择合适的算法对于提升OCR的识别准确率至关重要。在众多算法中&#xff0c;CRNN和Attention OCR犹如两颗璀璨的明珠&#xff0c;备受瞩目。 CRNN&#xff0c;这位结合了卷积神经网络&#xff08;CNN&#xff09;和…

电子电器架构 —— 诊断数据DTC具体故障类型篇

电子电器架构 —— 诊断数据DTC具体故障类型篇 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师 (Wechat:gongkenan2013)。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 本就是小人物,输了就是输了,不要在意别人怎么看自己。江湖一碗茶,喝…

Spark Stage

Spark Stage 什么是Stage Spark中的一个Stage只不过是物理执行计划其中的一个步骤&#xff0c;它是物理执行计划的一个执行单元。一个Job会被拆分为多组Task&#xff0c;每组任务被称为一个Stage&#xff0c;可以简单理解为MapReduce里面的Map Stage&#xff0c; Reduce Stag…

Unity 中 苹果眼镜开发入口

1. 文档介绍了Unity对Apple新操作系统visionOS的支持。 2. Unity提供了完善的文档、模板和支持,帮助开发者快速为visionOS开发应用。 3. Unity的跨平台框架AR Foundation和XR Interaction Toolkit可以帮助现有移动和XR应用无缝迁移到visionOS。 4. 在visionOS上,可以利用Uni…

kafka(三)——librdkafka编译与使用(c++)

linux下编译 源码下载 git clone https://github.com/edenhill/librdkafka配置、编译和安装 # 进入目录 cd librdkafka/# 配置 ./configure# 编译 make# 安装 make install头文件和库目录 # 头文件 /usr/local/include/librdkafka rdkafkacpp.h rdkafka.h rdkafka_mock.h #…

LLM漫谈(五)| 从q star视角解密OpenAI 2027年实现AGI计划

最近&#xff0c;网上疯传OpenAI2027年关于AGI的计划。在本文&#xff0c;我们将针对部分细节以第一人称进行分享。​ 摘要&#xff1a;OpenAI于2022年8月开始训练一个125万亿参数的多模态模型。第一个阶段是Arrakis&#xff0c;也叫Q*&#xff0c;该模型于2023年12月完成训练&…

vue3+threejs新手从零开发卡牌游戏(十一):添加简单的手牌上场逻辑

首先优化之前的战域相关代码&#xff0c;主要是将战域分成两部分&#xff0c;上方是对方战域&#xff0c;下方是己方战域&#xff0c;然后修改了战域中格子的名称&#xff0c;方便后续不同手牌上场的逻辑区分&#xff1a; game/site/index.vue完整代码如下&#xff1a; <!…

【WEEK4】 【DAY4】AJAX第一部分【中文版】

【WEEK4】 【DAY4】AJAX第一部分【中文版】 2024.3.21 Thursday 目录 8.AJAX8.1.简介8.2.伪造ajax8.2.1.新建module&#xff1a;springmvc-06-ajax8.2.2.添加web支持&#xff0c;导入pom依赖8.2.2.1.修改web.xml8.2.2.2.新建jsp文件夹 8.2.3.新建applicationContext.xml8.2.4.…

快速入门Kotlin②控制流函数

控制流 if if是一个表达式&#xff0c;可以用于条件判断和控制流。 fun main() {// 传统用法val a 1val b 2var max aif (a < b) max b// With elsevar max2: Intif (a > b) {max2 a} else {max2 b}// 作为表达式val max3 if (a > b) a else b } when whe…

蓝桥杯刷题_day2

文章目录 DAY2杨辉三角查找整数数列特征字母图形(未通过全部样例) DAY2 杨辉三角 【题目描述】 杨辉三角形又称Pascal三角形&#xff0c;它的第i1行是(ab)i的展开式的系数。它的一个重要性质是&#xff1a;三角形中的每个数字等于它两肩上的数字相加。 下面给出了杨辉三角形的…

2024智能短信营销推广系统使用攻略

智能短信营销推广系统以其精准、高效的特点&#xff0c;成为企业与消费者建立联系的重要桥梁。云衔科技凭借其先进的技术和专业的服务&#xff0c;为企业提供了一套完善的智能短信营销推广系统解决方案&#xff0c;让企业在短时间内实现大规模、个性化的短信营销活动。 云衔科…

01---java面试八股文——mybatis-------10题

1、什么是MyBatis Mybatis是一个半ORM&#xff08;对象关系映射&#xff09;框架&#xff0c;它内部封装了JDBC&#xff0c;开发时只需要关注SQL语句本身&#xff0c;不需要花费精力去处理加载驱动、创建连接、创建statement等繁杂的过程。程序员直接编写原生态sql&#xff0c…