给你一个只包含 '(' 和 ')' 的字符串,找出最长有效(格式正确且连续)括号子串的长度。
示例 1:
输入:s = "(()"
输出:2
解释:最长有效括号子串是 "()"
示例 2:
输入:s = ")()())"
输出:4
解释:最长有效括号子串是 "()()"
示例 3:
输入:s = ""
输出:0
提示:
0 <= s.length <= 3 * 104
s[i] 为 '(' 或 ')'
题解一(动态规划):
class Solution {
public:
int longestValidParentheses(string s) {
int lenth = s.size();
vector<int> dp(lenth, 0);//不用int[]的形式是因为[]里要放常量
int maxi=0;
for (int i = 0; i < lenth; i++)
{
if(s[i]==')')
{
if (i == 0)
{
dp[i] = 0;
continue;
}
if (s[i - 1] == '(')//情况是...()
{
if ((i - 2) == -1)dp[i] = 2;
else
{
dp[i] = dp[i - 2] + 2;
}
}
else//情况是...))
{
//此处第一次判断是防止元素越界问题
if (i - dp[i - 1] - 1<0||s[i - dp[i - 1] - 1] == ')')
{
dp[i] = 0;
}
else
{
dp[i] = dp[i - 1] + 2 + ((i - dp[i - 1] - 2)>0?dp[i - dp[i - 1] - 2]:0);
}
}
maxi = max(maxi, dp[i]);
}
}
return maxi;
}
};
改后:
class Solution {
public:
int longestValidParentheses(string s) {
int lenth = s.size();
vector<int> dp(lenth, 0);//不用int[]的形式是因为[]里要放常量
int maxi = 0;
for (int i = 1; i < lenth; i++)
{
if (s[i] == ')')
{
if (s[i - 1] == '(')//情况是...()
{
if ((i - 2) == -1)dp[i] = 2;
else
{
dp[i] = dp[i - 2] + 2;
}
}
else//情况是...))
{
//此处第一次判断是防止第一个元素是')',但只要循环从1开始遍历就不会有这个问题
if (i - dp[i - 1] - 1 < 0 || s[i - dp[i - 1] - 1] == ')')
{
dp[i] = 0;
}
else
{
dp[i] = dp[i - 1] + 2 + ((i - dp[i - 1] - 2) > 0 ? dp[i - dp[i - 1] - 2] : 0);
}
}
maxi = max(maxi, dp[i]);
}
}
return maxi;
}
};
官方解法:
class Solution {
public:
int longestValidParentheses(string s) {
int maxans = 0, n = s.length();
vector<int> dp(n, 0);
for (int i = 1; i < n; i++) {
if (s[i] == ')') {
if (s[i - 1] == '(') {
dp[i] = (i >= 2 ? dp[i - 2] : 0) + 2;
} else if (i - dp[i - 1] > 0 && s[i - dp[i - 1] - 1] == '(') {
dp[i] = dp[i - 1] + ((i - dp[i - 1]) >= 2 ? dp[i - dp[i - 1] - 2] : 0) + 2;
}
maxans = max(maxans, dp[i]);
}
}
return maxans;
}
};
解法二(栈):
class Solution {
public:
int longestValidParentheses(string s) {
stack<int>stk;
stk.push(-1);
int tmp,maxi;
maxi = 0;tmp = 0;
for (int i = 0; i < s.size(); i++)
{
if (s[i] == '(')stk.push(i);
else
{
stk.pop();
if (stk.empty())
{
tmp = 0;
stk.push(i);
}
else
{
tmp = i - stk.top();
maxi = max(maxi, tmp);
}
}
}
return maxi;
}
};
栈中最底端的元素为 最后一个无法匹配的右括号的下标,
如果遇到左括号,将其放入栈中。
如果遇到右括号,弹出栈顶元素,并判断栈是否为空,若非空,则记录当前有效字串长度,并与最大值比较大小;若空,则说明该括号为最后一个无法匹配的右括号的下标,将其放入栈中。
注:一开始应将-1放入栈底当作是最后一个无法匹配的右括号的下标,因为若不放的话,第一个元素为左括号,他进入栈中变为栈底元素,但他并不是最后一个无法匹配的右括号的下标。
leetcode官方代码:
class Solution {
public:
int longestValidParentheses(string s) {
int left = 0, right = 0, maxlength = 0;
for (int i = 0; i < s.length(); i++) {
if (s[i] == '(') {
left++;
} else {
right++;
}
if (left == right) {
maxlength = max(maxlength, 2 * right);
} else if (right > left) {
left = right = 0;
}
}
left = right = 0;
for (int i = (int)s.length() - 1; i >= 0; i--) {
if (s[i] == '(') {
left++;
} else {
right++;
}
if (left == right) {
maxlength = max(maxlength, 2 * left);
} else if (left > right) {
left = right = 0;
}
}
return maxlength;
}
};