一. Longest Valid Parentheses
Given a string containing just the characters ‘(’ and ‘)’, find the length of the longest valid (well-formed) parentheses substring.
For “(()”, the longest valid parentheses substring is “()”, which has length = 2.
Another example is “)()())”, where the longest valid parentheses substring is “()()”, which has length = 4.
Difficulty:Hard
TIME:TIMEOUT
解法一(動態規劃)
看到這道題的時候,就想起了求最長迴文子序列的問題,不過兩道題的解法並不相同。
如果用一個數組表示以括號字符”)”結尾的最長有效括號序列,這道題最優子結構可以描述爲,並且用字母s表示輸入字符串:
- 如果s[i]==’)’ && s[i - 1]==’(‘,那麼dp[i]=dp[i-2]+2;
- 如果s[i]==’)’ && s[i - dp[i-1]-1] ==’(‘,那麼dp[i]=dp[i-1]+2+dp[i-dp[i-1]-2];
更直觀的表達就是這樣:
- 第一種情況可以稱之爲擴展,比如形如()()。
- 第二種情況可以稱之爲包含,比如形如(())。
對於有效括號序列來說,要不就是擴展,要不就是包含,沒有第三種情況。
int longestValidParentheses(string s) {
if(s.size() < 2)
return 0;
vector<int> dp(s.size(),0); //記錄以')'結尾的最長有效括號長度
int len = 0;
for(int i = 1; i < s.size(); i++) {
if(s[i] == ')' && s[i - 1] == '(') //擴展
dp[i] = i - 2 >= 0 ? dp[i - 2] + 2 : 2;
else if(s[i] == ')' && s[i - dp[i - 1] - 1] == '(') //包含
//注意這裏包含之後還要再擴展一次
dp[i] = i - dp[i - 1] - 2 >= 0 ? dp[i - 1] + 2 + dp[i - dp[i - 1] - 2] : dp[i - 1] + 2;
len = max(len, dp[i]);
}
return len;
}
代碼的時間複雜度爲
解法二(貪心算法)
這道題也可以用貪心來求解,不過需要用到棧。分爲以下幾種情況。
- 當遇到’(‘,將該字符的下標壓入棧中
- 當遇到’)’,如果這個時候棧爲空,說明字符’)’是多餘的,因此字符序列可以從這裏斷開
- 當遇到’)’,這個時候棧不爲空,這個時候就從棧中彈出一個下標,彈出下標之後如果棧爲空,說明這個字符序列完全是有效括號序列,如果彈出下標後棧不爲空,說明這個字符序列只有部分是有效括號序列,起始位置爲棧頂的下標。
int longestValidParentheses(string s) {
if(s.size() < 2)
return 0;
vector<int> v;
int left = -1;
int len = 0;
for(int i = 0; i < s.size(); i++) {
if(s[i] == '(')
v.push_back(i);
else if(v.empty())
left = i;
else {
v.pop_back();
if(v.empty())
len = max(len, i - left); //棧中元素完全匹配
else
len = max(len, i - v.back()); //棧中元素不完全匹配,計算部分長度
}
}
return len;
}
代碼的時間複雜度爲