32. 最长有效括号
给定一个只包含 '(' 和 ')' 的字符串,找出最长的包含有效括号的子串的长度。
示例 1:
输入: "(()"
输出: 2
解释: 最长有效括号子串为 "()"
示例 2:
输入: ")()())"
输出: 4
解释: 最长有效括号子串为 "()()"
思路
用栈解决这个问题:匹配 抵消
这题关键的一点是栈中保存index下标位置,而不是保存字符。将index保存在栈中,然后匹配的index会出栈,全部的抵消掉,剩下的就是不能匹配的index。两个不能匹配的下标index中间的都是能够匹配的,其中有两个细节需要注意,就是两边的边界:左边界是-1,右边界是s.size(),两个下标i,j之间的元素个数为:i+k+1=j,k=j-i-1.
代码实现
class Solution {
public:
int longestValidParentheses(string s) {
int n = s.size();
if(n==0 || n==1)
return 0;
stack<int> stk;
for(int i = 0;i < n;i++)//遍历一个个元素,流式处理
{
if(s[i]==')' && !stk.empty() && s[stk.top()] == '(')
stk.pop();
else
stk.push(i);
}
if(stk.empty())
return n;
int ret = 0;
int right = n;
while(!stk.empty())
{
int left = stk.top();
stk.pop();
ret = max(ret,right-left-1);
right = left;
}
ret = max(ret,right);
return ret;
}
};
方法2
思路
和上面的用栈的思路一样,但是实现不同,我们边做边更新,只需要一次遍历
代码实现
class Solution {
public:
int longestValidParentheses(string s) {
int n = s.size();
if(n==0 || n==1)
return 0;
int ret = 0;
stack<int> stk;
//流式处理,其实这里用栈模拟了动态规划中间操作的流程
//遇到能和当前的")"匹配的情况时,我们计算得到的长度不是
//局部的这个匹配串的长度,而是整体的字符串中以这个")"
//结尾的最长的包含有效括号的子串的长度
for(int i = 0; i < n; ++i)
{
if(s[i]==')' && !stk.empty() && s[stk.top()]=='(')
{
stk.pop();//向左尽量扩展
if(!stk.empty())
ret = max(ret, i-stk.top());
else
ret = max(ret, i + 1);
}
else
stk.push(i);
}
return ret;
}
};
方法3
思路
动态规划:
dp[i]:
由当前的')'与之对应匹配的'('(假设它的下标为index)之间形成的局部长度+dpindex-1](向左能扩展的最大长度)
代码实现
class Solution {
public:
int longestValidParentheses(string s) {
int n = s.size();
if(n==0 || n==1)
return 0;
vector<int> dp(n, 0);//dp[i]表示以当前位置为终点的最长长度,则只能在')'处更新
int ret = 0;
for(int i = 1; i < n; i++)//动态规划,流式处理
{
if(s[i] == '(')
dp[i] = 0;
else
{
int index = i-dp[i-1]-1;
if(index >= 0 && s[index]=='(')
{
dp[i] = dp[i-1] + 2;
if(index-1 >= 0)
dp[i] += dp[index-1];
}
}
ret = max(ret, dp[i]);
}
return ret;
}
};