携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第2天,点击查看活动详情
题目
给你一个只包含 '(' 和 ')' 的字符串,找出最长有效(格式正确且连续)括号子串的长度。
示例 1
输入:s = "(()"
输出:2
解释:最长有效括号子串是 "()"
示例 2
输入:s = ")()())"
输出:4
解释:最长有效括号子串是 "()()"
示例 3
输入:s = ""
输出:0
提示
0 <= s.length <= 3 * 104s[i]为'('或')'
题解
思路
在括号匹配问题当中,栈是非常通用、经典的解法。在这道题目中,用栈来做并不那么显然。但栈的方法比起动态规划之类的还是更加方便。
从左向右遍历,遇到'(',就把下标放到栈里。
(把下标放进去怎么用呢?因为本题只有'('')'两个元素,')'又不入栈,栈里只有一种元素,所以只有下标可以记录啦)
如果遇上')',说明一对括号已经匹配完成了。那么我们记录一次合法的子串长度。末端肯定是当前的下标,但起始端呢?
如果以当前栈顶的元素,即被匹配的'('作为起始段,那之前已经匹配完成的括号对就无法计入了,比如数据"(()()()"。
所以,在将当前的栈顶元素弹出栈后,选择现在的[栈顶元素+1]作为起始端(也就是正在等待匹配的'(')。这样,就可以囊括所有的已经匹配完成的括号对。
那如果在这之中,有不合法的括号怎么办?不合法的括号,一定是')'。为什么会不合法?因为当遍历到')'时,。没有响应的'('与之匹配,即栈为空。所以我们如果选择栈顶元素+1作为起始端,不会出现该处恰好为')'、包含不合法子串的现象。
那如果说弹出'('后,栈为空,以什么为起始呢?如果弹完后空栈,说明当前遍历到的所有括号都已完成匹配,没有多余的'('。那起始端就是上一个[不合法的')'+1]。所以遇到这种不合法的情况时,我们需要记录一下。栈非空的情况,stack[len]+1是起始端,那么为了方便,但栈空的时候len=0,我们将上一个不合法下标记录在stack[0]中。
当没出现过不合法情况时,即从s[0]开始都是合法的,那么stack[0]就初始化为0的前一位,即-1。
代码
class Solution {
public:
int longestValidParentheses(string s) {
int ans=0;
int stack[30005];
int len=0;
stack[0]=-1;
for(int i=0;i<s.length();i++){
if(s[i]=='('){
stack[++len]=i;
}else{
if(len){
len--;
ans=max(ans,i-stack[len]);
}else stack[0]=i;
}
}
return ans;
}
};
结语
业精于勤,荒于嬉;行成于思,毁于随。