Leetcode: 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.
分析:这里我们分析解决这道题的两种方法,一种是利用栈,另一种是动态规划。
1. 利用栈,时间复杂度O(n), 空间复杂度O(n)
在valid parentheses中,我们用最后栈是否为空,判断是否为valid parentheses。这里要求longest valid parentheses,我们要在valid parentheses的基础上做些改动。我们首先应该考虑的是,对于每一段valid parentheses,我们怎么记录它的长度,如果在遍历过程中求的每一段valid parentheses的长度,我们可以轻松的找出最长的。 通过观察可以发现,当前valid parentheses的长度为当前')'的index减去栈顶'('的index(此时与当前')'匹配的'('已被pop出)。如果当栈为空时,我们无法通过上述方法求的长度,此种情况,或者该valid parentheses段前面有')'或者前面没有任何字符,这两种情况我们可以通过记录上一次栈空时')'的index,然后当前')'的index减去上一次')'的index即为valid parentheses段的长度。代码如下:
1 class Solution { 2 public: 3 int longestValidParentheses(string s) { 4 int n = s.length(); 5 if(n == 0) return 0; 6 int longest = 0, last = -1;//last is the index of last ')' 7 stack<int> S; 8 9 for(int i = 0; i < n; i++){ 10 if(s[i] == '(') S.push(i); 11 else if(S.empty()){ 12 last = i; 13 }else{ 14 S.pop(); 15 if(S.empty()) longest = max(longest, i - last); 16 else longest = max(longest, i - S.top()); 17 } 18 } 19 return longest; 20 } 21 };
2. 动态规划,时间复杂度O(n), 空间复杂度O(n)。
我们用f[i]记录在[i, n-1]段中从i开始的valid parentheses最大长度。递推公式如下:
if(i+f[i+1]+1 < n && s[i] == '(' && s[i+f[i+1]+1] == ')') f[i] = f[i+1] + 2 +(i+f[i+1] +2 < n)?f[i+f[i+1]+2]:0;otherwise f[i] = 0.
代码如下:
1 class Solution { 2 public: 3 int longestValidParentheses(string s) { 4 vector<int> f(s.size(), 0); 5 int ret = 0; 6 for (int i = s.size() - 2; i >= 0; --i) { 7 int match = i + f[i + 1] + 1; 8 // case: "((...))" 9 if (s[i] == '(' && match < s.size() && s[match] == ')') { 10 f[i] = f[i + 1] + 2; 11 // if a valid sequence exist afterwards "((...))()" 12 if (match + 1 < s.size()) f[i] += f[match + 1]; 13 } 14 ret = max(ret, f[i]); 15 } 16 return ret; 17 } 18 };