符合直觉的做法是:分别计算以 i 开头的 最长有效括号(i 从 0 到 n - 1·),从中取出最大的即可。
代码
代码支持: Python
classSolution:deflongestValidParentheses(self,s:str) ->int: n =len(s) ans =0defvalidCnt(start):# cnt 为 ) 的数量减去 ( 的数量 cnt =0 ans =0for i inrange(start, n):if s[i]=='(': cnt +=1if s[i]==')': cnt -=1if cnt <0:return i - startif cnt ==0: ans =max(ans, i - start +1)return ansfor i inrange(n): ans =max(ans, validCnt(i))return ans
// 用栈来解varlongestValidParentheses=function (s) {let stack =newArray();let longest =0;stack.push(-1);for (let i =0; i <s.length; i++) {if (s[i] ==="(") {stack.push(i); } else {stack.pop();if (stack.length===0) {stack.push(i); } else { longest =Math.max(longest, i - stack[stack.length-1]); } } }return longest;};
Python Code:
classSolution:deflongestValidParentheses(self,s:str) ->int:ifnot s:return0 res =0 stack = [-1]for i inrange(len(s)):if s[i]=="(": stack.append(i)else: stack.pop()ifnot stack: stack.append(i)else: res =max(res, i - stack[-1])return res
CPP Code:
classSolution {public:intlongestValidParentheses(string s) { stack<int> st;st.push(-1);int ans =0;for (int i =0; i <s.size(); ++i) {if (s[i] ==')'&&st.top() !=-1&&s[st.top()] =='(') {st.pop(); ans =max(ans, i -st.top()); } elsest.push(i); }return ans; }};
复杂度分析
时间复杂度:$O(N)$
空间复杂度:$O(N)$
O(1) 空间
思路
我们可以采用解法一中的计数方法。
从左到右遍历一次,并分别记录左右括号的数量 left 和 right。
如果 right > left ,说明截止上次可以匹配的点到当前点这一段无法匹配,重置 left 和 right 为 0
如果 right == left, 此时可以匹配,此时有效括号长度为 left + right,我们获得一个局部最优解。如果其比全局最优解大,我们更新全局最优解
publicclassSolution {publicintlongestValidParentheses(String s) {int left =0, right =0, maxlength =0;for (int i =0; i <s.length(); i++) {if (s.charAt(i) =='(') { left++; } else { right++; }if (left == right) { maxlength =Math.max(maxlength, left + right); }if (right > left) { left = right =0; } } left = right =0;for (int i =s.length() -1; i >=0; i--) {if (s.charAt(i) =='(') { left++; } else { right++; }if (left == right) { maxlength =Math.max(maxlength, left + right); }if (left > right) { left = right =0; } }return maxlength; }}
Python3 Code:
classSolution:deflongestValidParentheses(self,s:str) ->int: ans = l = r =0for c in s:if c =='(': l +=1else: r +=1if l == r: ans =max(ans, l + r)if r > l: l = r =0 l = r =0for c in s[::-1]:if c =='(': l +=1else: r +=1if l == r: ans =max(ans, l + r)if r < l: l = r =0return ans
CPP Code:
classSolution {public:intlongestValidParentheses(string s) {int left =0, right =0, ans =0, N =s.size();for (int i =0; i < N; ++i) { left +=s[i] =='('; right +=s[i] ==')';if (left == right) ans =max(ans, left + right);elseif (right > left) left = right =0; } left =0, right =0;for (int i = N -1; i >=0; --i) { left +=s[i] =='('; right +=s[i] ==')';if (left == right) ans =max(ans, left + right);elseif (left > right) left = right =0; }return ans; }};
动态规划
思路
所有的动态规划问题, 首先需要解决的就是如何寻找合适的子问题. 该题需要我们找到最长的有效括号对, 我们首先想到的就是定义dp[i]为前 i 个字符串的最长有效括号对长度, 但是随后我们会发现, 这样的定义, 我们无法找到 dp[i]和 dp[i-1]的任何关系. 所以, 我们需要重新找一个新的定义: 定义dp[i]为以第 i 个字符结尾的最长有效括号对长度. 然后, 我们通过下面这个例子找一下 dp[i]和 dp[i-1]之间的关系.
s ='(())())'
从上面的例子我们可以观察出一下几点结论(描述中 i 为图中的 dp 数组的下标, 对应 s 的下标应为 i-1, 第 i 个字符的 i 从 1 开始).
base case: 空字符串的最长有效括号对长度肯定为 0, 即: dp[0] = 0;
s 的第1个字符结尾的最长有效括号对长度为 0, s 的第2个字符结尾的最长有效括号对长度也为 0, 这个时候我们可以得出结论: 最长有效括号对不可能以'('结尾, 即: dp[1] = d[2] = 0;