题目:https://leetcode-cn.com/problems/longest-valid-parentheses/
参考了官方orz
dp做法:
表示前
个字符能得到的最大长度
class Solution {
public:
int longestValidParentheses(string s) {
int n = s.length();
vector<int> dp;
dp.resize(n+1);
int ans = 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-1-dp[i-1] >= 0 && s[i-1-dp[i-1]] == '(')
dp[i] = dp[i-1] + (i-2-dp[i-1] >= 0 ? dp[i-2-dp[i-1]] : 0) + 2;
ans = max(ans,dp[i]);
}
}
printf("%d\n",ans);
return ans;
}
};
栈做法
class Solution {
public:
int longestValidParentheses(string s) {
int n = s.length();
stack<int> st;
int ans = 0;
st.push(-1);
for(int i = 0,x;i < n;i++) {
if(s[i] == '(') st.push(i);
else{
st.pop();
if(st.empty()) st.push(i);
else ans = max(ans,i-st.top());
}
}
printf("%d\n",ans);
return ans;
}
};
更精简做法,用
记录左括号数,用
记录右括号数,从左到右遍历,当
时更新答案;再从右到左遍历一遍。
正确性证明:我们在从左到右遍历时,会漏掉统计的情况就是
的情况,如
,而这确是从右到左遍历会考虑到的。这两种遍历相辅相成,考虑了所有的情况。
class Solution {
public:
int longestValidParentheses(string s) {
int n = s.length();
int l = 0,r = 0;
int ans = 0;
for(int i = 0;i < n;i++) {
if(s[i] == '(') l++;
else r++;
if(l == r) ans = max(ans,2*l);
else if(l < r) l = r =0;
}
l = 0,r = 0;
for(int i = n-1;i >= 0;i--) {
if(s[i] == '(') l++;
else r++;
if(l == r) ans = max(ans,2*l);
else if(l > r) l = r =0;
}
printf("%d\n",ans);
return ans;
}
};