给定一个只包含 '('
和 ')'
的字符串,找出最长的包含有效括号的子串的长度。
示例 1:
输入: "(()"
输出: 2
解释: 最长有效括号子串为 "()"
示例 2:
输入: ")()())
" 输出: 4 解释: 最长有效括号子串为"()()"
思路:这个题目和前面一个有效括号很类似,不过那个是判断整个字符串是否是合法的括号,这个要从字符串中找到最长的有效字符串。还可以用栈来实现,也可以想到动态规划,不过个人觉得动态规划的方法比较难以理解。
用栈来实现,我一开始的实现方式是:遇到左括号就压栈,遇到右括号,则要判断栈顶是否是左括号来匹配,如果是的话,将栈顶出栈,配成一组合法的括号,但是这里应该注意,这里不能直接在最后结果上加上长度2。因为像这种情况“(()(”,虽然中间第二个和第三个可以匹配成一个合法括号,但是最后一个和第一个并没有匹配成功,所以前面的那个并不能算入结果中。我们可以想到,当我将栈顶出栈之后,如果栈为空了,证明我这个目前的字符串一定是合法的,而且是可计入结果的。
所以要先暂时存起来一个结果,栈为空时,才能计入最终的最长有效的长度中。
最后从第一个字符开始暴力求解,求以每个字符串为首的最长有效括号的长度,最后得到最大的一个长度。
int isValid(string s) { stack<int> sta; int num=0; int t=0; for(int i=0;i<s.size();i++) { if(s[i]=='(' ) sta.push(s[i]); else if(sta.empty()) { return num; } else if(s[i]==')' && !sta.empty()) { sta.pop(); t+=2; if(sta.empty()) { num+=t; t=0; } } else { return num; } } return num; } int longestValidParentheses(string s) { int len=s.size(); if(len==0 || len==1) return 0; int maxlen=0; for(int i=0;i<len;i++) { maxlen=max(maxlen,isValid(s.substr(i,len))); } return maxlen; }
上述的解法时间复杂度肯定是高的,因为它要从每个字符开始求解来找到最大值。
我们其实直接将字符的下标压栈,这样就可以通过下标的减法就可以得到字符串的长度了。从头遍历,当前字符为左括号时,压栈,当前字符为右括号时,分为栈中为空(重新选当前字符下一个为起始点),栈中为1(长度为j-i+1),栈中个数大于1(接着匹配,看以后是否还有合法的括号)
int longestValidParentheses(string s) { int ans = 0; stack<int> stk; for (int i = 0, j = 0; j < s.size(); j++) { if (s[j] == '(') { stk.push(j); } else { if (stk.size() > 1) { stk.pop(); ans = max(ans, j - stk.top()); } else if (stk.size() == 1) { stk.pop(); ans = max(ans, j - i + 1); } else { i = j + 1;//i用来表示起始点 } } } return ans; }