题目
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)先将 string 转化为更容易操作的数组,'(' 是1, ')' 是-1;
(2)用 left 和 right 指针记录最大长度的子串左右边界,并用sum记录当前的和:
如果sum==0,表示已经匹配,更新最大值 max = max>(right+1-left)?max:(right+1-left) ;
如果sum>0,表示未匹配,需要右移 right ;
如果sum<0,表示匹配过当,需要将左边界 left 更新至 right+1 的位置;
(3)当然会出现结束时sum>0的情况,例如 ( ( ( ) ( ) ) ,遍历结束时sum=1,left=0,right=7,始终都未更新max。
这是就需要一个翻转操作,即将结束时 left~rght-1的字符串翻转(位置和值同时翻转),再接着遍历left~rght-1,更新max。
(4)具体实现时,只需要两遍遍历即可:从前到后 maxLR ,从后到前 maxRL ,再取两者最大值,即为结果。
class Solution {
public:
int longestValidParentheses(string s) {
// Start typing your C/C++ solution below
// DO NOT write int main() function
int len = s.length();
if(len<2) return 0;
vector<int> value(len,0);
for(int i=0;i<len;i++) {
if(s[i]=='(') value[i]=1;
if(s[i]==')') value[i]=-1;
}
int maxLR = maxlenLR(value);
int maxRL = maxlenRL(value);
return max(maxLR,maxRL);
}
int maxlenLR(vector<int> &value) {
int sum=0;
int max = 0;
int left=0,right=0;
while(right<value.size()) {
sum+=value[right];
if(sum<0) {
if(right-left>max)
max=right-left;
left=right+1;
right=left;
sum=0;
continue;
}
if(sum==0) {
max = max>(right+1-left)?max:(right+1-left);
}
right++;
}
if(sum==0){
max = max>(right-left)?max:(right-left);
}
return max;
}
int maxlenRL(vector<int> &value) {
int sum=0;
int max = 0;
int left=value.size()-1,right=value.size()-1;
while(left>=0) {
sum+=value[left];
if(sum>0) {
if(right-left>max)
max=right-left;
right=left-1;
left=right;
sum=0;
continue;
}
if(sum==0) {
max = max>(right+1-left)?max:(right+1-left);
}
left--;
}
if(sum==0){
max = max>(right-left)?max:(right-left);
}
return max;
}
};时间复杂度是 O(3*N) 的,空间复杂度是O(N) 。
再优化一下代码长度 :时间复杂度为 O(2*N),空间复杂度是O(1)
class Solution {
public:
int longestValidParentheses(string s) {
// Start typing your C/C++ solution below
// DO NOT write int main() function
int len = s.length();
if(len<2) return 0;
int maxLR = maxlenLR(s);
int maxRL = maxlenRL(s);
return max(maxLR,maxRL);
}
int value(char c) {
if(c=='(') return 1;
if(c==')') return -1;
}
int maxlenLR(string &s) {
int sum=0;
int max = 0;
int left=0,right=0;
while(right<s.size()) {
sum+=value(s[right]);
if(sum<0) {
max = max>(right-left)?max:(right-left);
left=right+1;
sum=0;
}
if(sum==0) {
max = max>(right+1-left)?max:(right+1-left);
}
right++;
}
if(sum==0){
max = max>(right-left)?max:(right-left);
}
return max;
}
int maxlenRL(string &s) {
int sum=0;
int max = 0;
int left=s.size()-1,right=s.size()-1;
while(left>=0) {
sum+=value(s[left]);
if(sum>0) {
max = max>(right-left)?max:(right-left);
right=left-1;
sum=0;
}
if(sum==0) {
max = max>(right+1-left)?max:(right+1-left);
}
left--;
}
if(sum==0){
max = max>(right-left)?max:(right-left);
}
return max;
}
};
思路二
用栈保存 '(' 的位置,如果遇到 ')' :
(1)若栈非空,则表示可以匹配,将 '(' 和 ')' 都置为 'Q' ;
(2)若栈为空,则表示当前的 ')' 不能匹配,则继续往下找;
然后遍历修改之后的 字符串,找到最长的连续 'Q' 序列,即为结果。
class Solution {
public:
int longestValidParentheses(string s) {
// Start typing your C/C++ solution below
// DO NOT write int main() function
int len = s.length();
if(len<2) return 0;
stack<int> mystack;
for(int i=0;i<len;i++) {
if(s[i]=='(') {
mystack.push(i);
}
if(s[i]==')') {
if(!mystack.empty()) {
s[i]='Q';
s[mystack.top()]='Q';
mystack.pop();
}
}
}
int cur = 0;
int max = 0;
for(int i=0;i<len;i++) {
if(s[i]=='Q') {
cur++;
} else {
max = max>cur?max:cur;
cur=0;
}
}
max = max>cur?max:cur;
return max;
}
}; 时间复杂度为 O(2*N),空间复杂度是O(N) .
本文介绍两种高效算法来寻找给定字符串中最长的有效括号子串长度。第一种算法通过两次遍历并使用指针记录子串边界,第二种算法则利用栈结构标记匹配的括号,最终遍历字符串找出最长连续匹配部分。
219

被折叠的 条评论
为什么被折叠?



