3381 字
约 11 分钟
8
LeetCode刷题Java版032.最长有效括号
无标签

LeetCode刷题Java版032.最长有效括号

作者:沉默王二
发布时间:2022-08-26T14:26:46.791+0800


032.最长有效括号

题意

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

难度

困难

示例

输入:s = "(()"

解释:最长有效括号子串是 "()"

输入:s = ")()())"

解释:最长有效括号子串是 "()()"

分析

还记得之前判断**有效括号 **那道题吗?

当时,我们利用了栈这个数据结构,当我们遇到一个右括号,就看一看栈内有没有相应的左括号,如果栈为空或者说栈顶的左括号与之不匹配,那么它就不是一个有效的括号序列。

换言之,但凡是匹配的,从栈顶括号的位置,到现在的右括号位置的均为合法的!

而且这题没有多种括号。

那是不是只要我们在遇到左括号的时候,将它压入栈中,遇到右括号的时候直接弹出栈顶(也就是与左括号相匹配的右括号的位置),然后再计算长度就可以解决这个困难题目了?

很不幸,不能,因为这个想法是有纰漏的。

比如这样子的一组数据:()() 我们如果只是单纯记录每个左右括号相匹配的位置,然后算出长度,这样子只能得到2,而不能得出正确答案——4。

所以我们需要转变思路。

那能不能通过记录上一个没有匹配的右括号 + 1的位置,来作为新的合法子串的开始呢?

可能有人会问,像上面的那组数据我们还是不能得出答案啊。没关系,我们可以先人为的在栈中插入一个初始位置-1。匹配成功的时候,我们先不着急统计答案,而是直接弹出栈顶,表示栈顶的左括号已经匹配掉了,然后这时候的长度,就是当前位置 - 栈顶元素,因为弹出了之后,我们能够得到的就是以当前这个右括号结尾的最长有效括号的长度。

我们再来按照这个思路来将 ()() 模拟一遍。

stack = [-1]     pos = 0   s[pos] = '('     此时为左括号,入栈

stack = [-1]     pos = 2   s[pos] = '('     此时为左括号,入栈stack = [-1,2]   pos = 3   s[pos] = ')'     此时为右括号,与栈顶元素匹配,栈顶元素出战,统计答案为,(pos - stack.top()),即(3 - (-1)),就是4

这样子是不是思路就豁然开朗了?

如果我们只是按照先前一开始的思路,就没办法计算多个相互独立的合法括号序列的组合的答案,而通过保持栈底元素为 ‘最后一个没有被匹配的右括号的坐标',我们就能够得到整个合法括号序列的长度。

具体代码实现:

class Solution {

        int ans = 0;        Stack sta = new Stack<>();        sta.push(-1);        for(int i = 0;i < s.length();i++){            if(s.charAt(i) == '(')                sta.push(i);            else{                sta.pop();                if(sta.empty())                    sta.push(i);                else{                    int num = sta.pop();                    ans = Math.max(ans,i - num);                    sta.push(num);                }            }        }        return ans;    }}

嗯,只打败了不到 10%的战友,不过没关系,毕竟 hard 模式,先搞定再说。

总结

我们先前学习了合法括号的判断,但是对于当前这道题目,如果我们盲目套用先前的知识,直接莽,去枚举所有的子串,然后再一一去考虑他们是不是合法的,接着再统计答案,时间复杂度直接飙升到了,而通过之前思路的稍微转换,而不是死板硬套,最后实现的算法时间复杂度是,我们只需要遍历一遍整个字符串,就可以得出答案了。

力扣链接:https://leetcode.cn/problems/longest-valid-parentheses/

一步一个脚印

不积跬步无以至千里,不积小流无以成江海。LeetCode - 100天从算法小白到卷王正式启动了,我们计划周一到周五至少每天更新一篇,周六周日更新一篇,目标 300 道 LeetCode 经典题。

PDF 版本目前只针对**二哥编程星球 的球友开放,如果你也想一起打卡学习算法的话,戳链接 **加入我们吧。

一个人可以走得很快,但一群人才能走得更远。二哥编程星球 (目前已有 710 多名球友加入)里面的每个球友都非常的友善,除了鼓励你,还会给你提出合理的建议,一起冲!

032.最长有效括号

题意

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

难度

困难

示例

输入:s = "(()"

解释:最长有效括号子串是 "()"

输入:s = ")()())"

解释:最长有效括号子串是 "()()"

分析

还记得之前判断**有效括号 **那道题吗?

当时,我们利用了栈这个数据结构,当我们遇到一个右括号,就看一看栈内有没有相应的左括号,如果栈为空或者说栈顶的左括号与之不匹配,那么它就不是一个有效的括号序列。

换言之,但凡是匹配的,从栈顶括号的位置,到现在的右括号位置的均为合法的!

而且这题没有多种括号。

那是不是只要我们在遇到左括号的时候,将它压入栈中,遇到右括号的时候直接弹出栈顶(也就是与左括号相匹配的右括号的位置),然后再计算长度就可以解决这个困难题目了?

很不幸,不能,因为这个想法是有纰漏的。

比如这样子的一组数据:()() 我们如果只是单纯记录每个左右括号相匹配的位置,然后算出长度,这样子只能得到2,而不能得出正确答案——4。

所以我们需要转变思路。

那能不能通过记录上一个没有匹配的右括号 + 1的位置,来作为新的合法子串的开始呢?

可能有人会问,像上面的那组数据我们还是不能得出答案啊。没关系,我们可以先人为的在栈中插入一个初始位置-1。匹配成功的时候,我们先不着急统计答案,而是直接弹出栈顶,表示栈顶的左括号已经匹配掉了,然后这时候的长度,就是当前位置 - 栈顶元素,因为弹出了之后,我们能够得到的就是以当前这个右括号结尾的最长有效括号的长度。

我们再来按照这个思路来将 ()() 模拟一遍。

stack = [-1]     pos = 0   s[pos] = '('     此时为左括号,入栈

stack = [-1]     pos = 2   s[pos] = '('     此时为左括号,入栈stack = [-1,2]   pos = 3   s[pos] = ')'     此时为右括号,与栈顶元素匹配,栈顶元素出战,统计答案为,(pos - stack.top()),即(3 - (-1)),就是4

这样子是不是思路就豁然开朗了?

如果我们只是按照先前一开始的思路,就没办法计算多个相互独立的合法括号序列的组合的答案,而通过保持栈底元素为 ‘最后一个没有被匹配的右括号的坐标',我们就能够得到整个合法括号序列的长度。

具体代码实现:

class Solution {

        int ans = 0;        Stack sta = new Stack<>();        sta.push(-1);        for(int i = 0;i < s.length();i++){            if(s.charAt(i) == '(')                sta.push(i);            else{                sta.pop();                if(sta.empty())                    sta.push(i);                else{                    int num = sta.pop();                    ans = Math.max(ans,i - num);                    sta.push(num);                }            }        }        return ans;    }}

嗯,只打败了不到 10%的战友,不过没关系,毕竟 hard 模式,先搞定再说。

总结

我们先前学习了合法括号的判断,但是对于当前这道题目,如果我们盲目套用先前的知识,直接莽,去枚举所有的子串,然后再一一去考虑他们是不是合法的,接着再统计答案,时间复杂度直接飙升到了,而通过之前思路的稍微转换,而不是死板硬套,最后实现的算法时间复杂度是,我们只需要遍历一遍整个字符串,就可以得出答案了。

力扣链接:https://leetcode.cn/problems/longest-valid-parentheses/

一步一个脚印

不积跬步无以至千里,不积小流无以成江海。LeetCode - 100天从算法小白到卷王正式启动了,我们计划周一到周五至少每天更新一篇,周六周日更新一篇,目标 300 道 LeetCode 经典题。

PDF 版本目前只针对**二哥编程星球 的球友开放,如果你也想一起打卡学习算法的话,戳链接 **加入我们吧。

一个人可以走得很快,但一群人才能走得更远。二哥编程星球 (目前已有 710 多名球友加入)里面的每个球友都非常的友善,除了鼓励你,还会给你提出合理的建议,一起冲!

032.最长有效括号

题意

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

难度

困难

示例

输入:s = "(()"

解释:最长有效括号子串是 "()"

输入:s = ")()())"

解释:最长有效括号子串是 "()()"

分析

还记得之前判断**有效括号 **那道题吗?

当时,我们利用了栈这个数据结构,当我们遇到一个右括号,就看一看栈内有没有相应的左括号,如果栈为空或者说栈顶的左括号与之不匹配,那么它就不是一个有效的括号序列。

换言之,但凡是匹配的,从栈顶括号的位置,到现在的右括号位置的均为合法的!

而且这题没有多种括号。

那是不是只要我们在遇到左括号的时候,将它压入栈中,遇到右括号的时候直接弹出栈顶(也就是与左括号相匹配的右括号的位置),然后再计算长度就可以解决这个困难题目了?

很不幸,不能,因为这个想法是有纰漏的。

比如这样子的一组数据:()() 我们如果只是单纯记录每个左右括号相匹配的位置,然后算出长度,这样子只能得到2,而不能得出正确答案——4。

所以我们需要转变思路。

那能不能通过记录上一个没有匹配的右括号 + 1的位置,来作为新的合法子串的开始呢?

可能有人会问,像上面的那组数据我们还是不能得出答案啊。没关系,我们可以先人为的在栈中插入一个初始位置-1。匹配成功的时候,我们先不着急统计答案,而是直接弹出栈顶,表示栈顶的左括号已经匹配掉了,然后这时候的长度,就是当前位置 - 栈顶元素,因为弹出了之后,我们能够得到的就是以当前这个右括号结尾的最长有效括号的长度。

我们再来按照这个思路来将 ()() 模拟一遍。

stack = [-1]     pos = 0   s[pos] = '('     此时为左括号,入栈

stack = [-1]     pos = 2   s[pos] = '('     此时为左括号,入栈stack = [-1,2]   pos = 3   s[pos] = ')'     此时为右括号,与栈顶元素匹配,栈顶元素出战,统计答案为,(pos - stack.top()),即(3 - (-1)),就是4

这样子是不是思路就豁然开朗了?

如果我们只是按照先前一开始的思路,就没办法计算多个相互独立的合法括号序列的组合的答案,而通过保持栈底元素为 ‘最后一个没有被匹配的右括号的坐标',我们就能够得到整个合法括号序列的长度。

具体代码实现:

class Solution {

        int ans = 0;        Stack sta = new Stack<>();        sta.push(-1);        for(int i = 0;i < s.length();i++){            if(s.charAt(i) == '(')                sta.push(i);            else{                sta.pop();                if(sta.empty())                    sta.push(i);                else{                    int num = sta.pop();                    ans = Math.max(ans,i - num);                    sta.push(num);                }            }        }        return ans;    }}

嗯,只打败了不到 10%的战友,不过没关系,毕竟 hard 模式,先搞定再说。

总结

我们先前学习了合法括号的判断,但是对于当前这道题目,如果我们盲目套用先前的知识,直接莽,去枚举所有的子串,然后再一一去考虑他们是不是合法的,接着再统计答案,时间复杂度直接飙升到了,而通过之前思路的稍微转换,而不是死板硬套,最后实现的算法时间复杂度是,我们只需要遍历一遍整个字符串,就可以得出答案了。

力扣链接:https://leetcode.cn/problems/longest-valid-parentheses/

一步一个脚印

不积跬步无以至千里,不积小流无以成江海。LeetCode - 100天从算法小白到卷王正式启动了,我们计划周一到周五至少每天更新一篇,周六周日更新一篇,目标 300 道 LeetCode 经典题。

PDF 版本目前只针对**二哥编程星球 的球友开放,如果你也想一起打卡学习算法的话,戳链接 **加入我们吧。

一个人可以走得很快,但一群人才能走得更远。二哥编程星球 (目前已有 710 多名球友加入)里面的每个球友都非常的友善,除了鼓励你,还会给你提出合理的建议,一起冲!

            知识星球
            
    
    
        
        扫码加入星球
        查看更多优质内容
    
    https://wx.zsxq.com/mweb/views/joingroup/join_group.html?group_id=15522885221412
LeetCode刷题Java版032.最长有效括号
https://clxhxhhr.top/posts/2496/
作者
clxstart
发布于
2026-09-19
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。