题目:给定一串仅由' ( '和 ' )'组成的括号字符串s,由于整个括号串可能不全部匹配,但可能存在部分匹配,返回匹配的最长的括号数。
分析:注意题目中红色加粗的部分,它给我们解这道题带来了很大的便利,因为在当前访问到‘)’ 时,我们不用去判断栈顶元素是否为 ‘(’,因为没有除二者之外的字符,‘)’又不入栈,所以只要判断当前栈不空,那么就肯定是‘(’,肯定就是一个匹配的括号对。
由于要返回的是最大匹配长度,栈又只需要判断是否为空,我们向栈里压入什么呢?对,就是元素的下标。这样一来,我们就可以利用栈顶元素的下标来计算最长匹配了。
在任何时候,只要栈不空,那么存在栈里的元素的意义就是当前尚未被匹配的‘(’。因为若匹配,我们会进行pop操作,所以在进行一次匹配后,我们若判断栈不空,那就说明至少栈顶的元素是没有匹配的,而这个没有匹配的栈顶‘(’,极有可能到最后也得不到匹配,所以我们这时要及时的更新最大长度,那么当前的已经匹配的长度是多少呢?是当前访问元素的index - 栈顶元素的值。若进行一次匹配操作后,发现栈为空了,这说明什么呢?说明是处于连续的匹配中,这时我们也要跟新最大长度,因为极有可能在以后就不匹配了,当前这个匹配的最大结果要进行保留。但是此时,我们只有当前遍历元素的下标,另外一个值是什么呢?也就是减数是多少呢?所以我们还需要定义一个变量,用来表示每一次连续匹配的起始点,我们用当前的下标- 起始点 + 1 来表示当前的最大长度。那么若当前遍历的元素为‘)’,且此时栈为空,说明什么呢?说明在此之前,就没有多余的‘(’,说明这就是个坑,是个不匹配的点,此时我们要做些什么呢?简单的将该字符跳过,去处理下一个字符吗?回头看看我们刚才分析中,涉及到了一个连续匹配的起始点问题,对,我们要更改这个连续匹配的起始点,令其等于当前处理的‘)’字符的下一位置。
好了,经过这样的分析,代码就呼之欲出了。
//CODE
int longestValidParentheses(string s) {
if(s.size() <= 1) return 0;
int len = s.size();
//container to store the index of '('s in s
//which haven't been matched.
stack<int> cs;
int max_length = 0;
int index = 0;
//the start of the match sequence.
int imatch = 0;
const char left_parentheses = '(';
const char right_parentheses = ')';
while (index < len )
{
if(s[index] == left_parentheses){
cs.push(index++);
continue;
}
else{//right_parentheses
if(!cs.empty())//the top must be '('
{
cs.pop();//the top '(' has been matched, pop it.
//there is one '(' that unmatched.
//it's a potential unmatched '(', update the matched length in time
if(!cs.empty())
max_length = max(max_length, index - cs.top());
else
max_length = max(max_length, index - imatch + 1);
}
else //this is no '(' to match.
imatch = index + 1;
}
++index;
}//end while
return max_length;
}
说明:涉及最大最小的问题,dp应该可以解决,还没想好,但是觉得应该可以解决,明天吧。