题目大意:求最长有效括号的长度。此前有个简单的题,就是求所给字符串括号是否匹配,这个题的话所给的字符串并非都是有效的括号匹配。
题目分析:看这个题首先需要知道有效括号的几种情况。
一种呢,就是串联并列的括号,eg. "()()()()()()" ;
二是括号嵌套的情况,eg. "(((())))";
那么第三种呢就是两种的结合了,既有并列又有嵌套,"()((()()))"
首先嵌套的这种情况呢,是比较好求的,就是求和右括号匹配的左括号位置,然后索引之差就是该右括号结尾的有效括号长度了。需要特别关注的是括号的串联并列的情况,因为中间可能断链,所谓断链也即是 当前右括号匹配的左括号的前一个括号也为左括号(这样既不存在前面也是有效括号的情况),举个栗子: "()(()",这就是一个失败的串联情况。既然如此,需要一个额外的数组来记录每个右括号所能匹配的有效括号长度,然后判断前后两个有效括号是否能接在一起。是不是有点动态规划的感觉,哈哈,当前右括号的有效括号长度 = 当前长度 + (0 或者 前一个有效括号的长度)。分析到此,可以直接上代码了:
class Solution {
public:
int longestValidParentheses(string s) {
int res = 0;
stack<int> tt; // 存储左括号的索引
if(s.size() < 2) return 0;
int len = s.size();
int *cnt = (int *)malloc(sizeof(int)*len);
memset(cnt, 0, sizeof(int)*len); // 开辟一个数组用于记录右括号的有效匹配长度
for(int i=0;i<s.size();i++){
if(s[i]=='('){ // 左括号则入栈
tt.push(i);
} else if(s[i]==')' && !tt.empty()) { // 右括号同时栈不为空
int index = tt.top();
tt.pop();
cnt[i]+= (i-index+1); // 一次最长匹配,没有算串联的
// 判断左括号前一个括号是否为右括号
if(index > 0 && s[index-1]==')' && cnt[index-1]!=0)
cnt[i]+=cnt[index-1];
res = max(res, cnt[i]); // 记录当前最大值
}
}
return res;
}
};