LeetCode 32. Longest Valid Parentheses
DP
由于括号匹配的特殊性,合法的括号匹配最后一定是')',因此我们可以记录以每个字符为结尾的最长括号匹配数。
dp[i] = 以s[i]结尾的最长括号匹配数
递推公式有两种可能:
1. 如果s[i-1]=='(',dp[i] = dp[i-2] + 2
2. 如果s[i-1]==')',我们可以通过 dp[i-1] 找到以 s[i-1] 结尾的最长字符串,我们只需判断前一个字符 s[i-dp[i-1]-1] 是不是'(',如果是,那么 dp[i] = dp[i-dp[i-1]-2] + dp[i-1] + 2
base: dp[0] = 0
target: max dp[i]
当然dp的递推公式也可以把两种情况合并,因为如果 s[i-1]=='(', dp[i-1]一定为0,可以整合进公式。
整个流程非常类似 Kadane's algorithm。
class Solution { public: int longestValidParentheses(string s) { int n=s.size(); int res=0; vector<int> dp(n,0); // longest valid parentheses ending at index i for (int i=1;i<n;++i){ if (s[i]==')'){ if (s[i-1]=='(') dp[i] = (i-2>=0 ? dp[i-2] : 0) + 2; else if (s[i-1]==')' && i-dp[i-1]-1 >= 0 && s[i-dp[i-1]-1]=='('){ dp[i] = (i-dp[i-1]-2>=0 ? dp[i-dp[i-1]-2] : 0) + dp[i-1] + 2; } res = max(res, dp[i]); } } return res; } };
时间复杂度 O(n)
Stack
括号的题stack也是一种解题思路。我们可以用stack来抵消匹配的括号,问题是如何找到匹配括号的长度。
思路类似 LeetCode 42. Trapping Rain Water 的stack解法中的left,本题里 i-st.top() 就是当前')'结尾的最大长度。
我们需要往stack里事先加入一个-1,并且每次pop导致stack为空的话,我们需要将当前元素加入stack。
如 ()() ,到第二个'('时,stack里是 -1, 2,第二个')'会pop掉2,3-(-1)=4 就是当前最大长度。
class Solution { public: int longestValidParentheses(string s) { int res=0; stack<int> st; st.push(-1); for (int i=0;i<s.size();++i){ if (s[i]=='(') st.push(i); else{ st.pop(); if (st.empty()) st.push(i); res = max(res, i-st.top()); } } return res; } };
时间复杂度 O(n)