32. 最长有效括号
给定一个只包含 ‘(’ 和 ‘)’ 的字符串,找出最长的包含有效括号的子串的长度。
思路
动态规划
假定dp[i]表示以i为结尾的最长有效括号,只需考虑’)’,当s[i-1]==’(‘时,dp[i]=dp[i-2]+2(注意边界条件),当s[i-1]==’)‘时,需要考虑s[i-dp[i-1]-1],当s[i-dp[i-1]-1]==’('时,dp[i]=dp[i-1]+dp[i-dp[i-1]-2]+2。
代码
class Solution {
public:
int longestValidParentheses(string s) {
int n = s.size();
int ans = 0;
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] >= 1 && s[i - dp[i - 1] - 1] == '(') {
dp[i] = dp[i - 1] + (i - dp[i - 1] >= 2? dp[i - dp[i - 1] - 2] : 0) + 2;
}
}
ans = max(ans, dp[i]);
}
}
return ans;
}
};
栈
使用一个栈的栈底保存已遍历元素中最后一个没有被匹配的右括号的下标。当遍历的字符为’(‘时,直接入栈,当遍历到’)'时,先弹出栈顶元素匹配该括号,再判断栈是否为空,为空就将该右括号坐标入栈,不为空就将当前右括号坐标-栈顶元素就是以当前右括号为结尾的最长有效括号长度。
代码
class Solution {
public:
int longestValidParentheses(string s) {
int n = s.size();
int ans = 0;
stack<int> stk;
stk.push(-1);
for(int i = 0; i < n; i++) {
if(s[i] == '(') {
stk.push(i);
}
else {
stk.pop();
if(stk.empty()) {
stk.push(i);
}
else {
ans = max(ans, i - stk.top());
}
}
}
return ans;
}
};
正逆向结合
使用left和right分别统计字符串左右括号数量,顺序遍历时,当right==left时,统计一个有效括号长度,当right>left时,归零。
逆序遍历时,当right==left时,统计一个有效括号长度,当left>right时,归零。
代码
class Solution {
public:
int longestValidParentheses(string s) {
int left = 0, right = 0, ans = 0;
int n = s.size();
for(int i = 0; i < n; i++) {
if(s[i] == '(') {
left++;
}
else {
right++;
}
if(left == right) {
ans = max(ans, 2 * left);
}
else if(right > left) {
right = 0;
left = 0;
}
}
left = 0, right =0;
for(int i = n - 1; i >= 0; i--) {
if(s[i] == '(') {
left++;
}
else {
right++;
}
if(left == right) {
ans = max(ans, 2 * left);
}
else if(left > right) {
left = 0;
right =0;
}
}
return ans;
}
};