LC.32. 最长有效括号
挺好的一个题,这里主要再分析一下官方的解法。
思路:
1.。
令以下标结尾的字符串的最大长度为,显然,.
当,需要讨论两种情况。
,这样显然有.
,因为我们已知,我们可以找到的开始匹配的前面 一个位置即,显然如果,是不能更新的,因为一定是未被匹配的,不然会包含掉它,所以显然,才能与进行匹配,然后再加上的长度就可以了。
即
时间复杂度:
class Solution { public: int longestValidParentheses(string s) { int n=s.length(),ans=0; vector<int>dp(n,0); for(int i=1;i<n;i++){ if(s[i]=='(') dp[i]=0; else if(s[i-1]=='('){ dp[i]=(i>=2?dp[i-2]:0)+2; } else if(i-dp[i-1]>0&&s[i-1-dp[i-1]]=='(') dp[i]=(i-2-dp[i-1]>=0?dp[i-2-dp[i-1]]:0)+2+dp[i-1]; ans=max(ans,dp[i]); } return ans; } };
2.栈。
显然对于这样的后缀表达式问题,用栈是很方便的。这里是参考官方大大的解法,预先放一个元素,保证栈底是未被匹配的最后一个右括号下标,如果是左括号直接入栈,否则弹出栈顶元素,如果栈是空的表示不能更新,否则长度为
时间复杂度:
class Solution { public: int longestValidParentheses(string s) { int n=s.length(),ans=0; stack<int>sk;sk.push(-1); for(int i=0;i<n;i++){ if(s[i]=='(') sk.push(i); else { sk.pop(); if(sk.empty()) sk.push(i); else ans=max(ans,i-sk.top()); } } return ans; } };
3.统计左右括号数。
这种方法我觉得比第二种好理解点,先顺序遍历一遍,如果是左括号,否则,左右括号数相等就更新长度,若,则可以舍弃掉前面所有的括号,。
因为顺序遍历没有考虑到的情况,这样就更新不了。
所以再逆序遍历一遍,时.这样就考虑到所有情况了。
时间复杂度:
class Solution { public: int longestValidParentheses(string s) { int n=s.length(),ans=0; int l=0,r=0; for(int i=0;i<n;i++){ if(s[i]=='(') l++; else r++; if(l==r) ans=max(ans,l*2); else if(r>l) l=r=0; } l=r=0; for(int i=n-1;i>=0;i--){ s[i]=='('?l++:r++; if(l==r) ans=max(ans,l*2); else if(l>r) l=r=0; } return ans; } };