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.
问题:求最长有效括号子字符串。
解题思路:
第一次做,以为是求整个字符串的有效括号长度是多少,思考了一会用 stack 可以求到,心想好像蛮简单的。扔到 LeetCode 跑了一下,结果错误,才发下原来是求 连续的最长有效括号长度。
重新理解题意后,开始做第二次。
想象括号匹配,就像玩那种 “天天爱消除” 新游戏,相邻两个字符,左边为 '(', 右边为 ')',则匹配成功,匹配成功的字符被替换为 '.'。
通过最多 n/2 次遍历,就可以把 s 中全部有效括号替换为 '.', 然后统计下连续 '.' 个数,就是题目的解,耗时 O(n*n)。实现后,扔到 LeetCode 上面,居然通过了,就是慢了一些。
再思考有没有更快的方法了,联想到第一次做用的 stack,可以借助 stack 一次遍历就将全部有效括号替换为 '.'。
第一步:一次遍历,stack 只存放 '(' 的下标。
当找到一个 '(',则压进 stack ;
当找到一个 ')',则把 stack.top 对于的字符替换为 '.',并弹出 stack.pop()。耗时O(n)。
第二步:求出连续 '.' 的最长长度, 耗时O(n)。
1 stack<int> sk; 2 3 for (int i = 0; i < s.size(); i++) { 4 if (s[i] == ')') { 5 if (sk.empty()) { 6 continue; 7 }else{ 8 int idx = sk.top(); 9 sk.pop(); 10 s[idx] = marked; 11 s[i] = marked; 12 } 13 }else{ 14 // s[i] is '(' 15 16 sk.push(i); 17 } 18 } 19 20 21 int len = 0; 22 int maxL = 0; 23 for (int i = 0; i < s.size(); i++) { 24 if (s[i] == '.') { 25 len++; 26 }else{ 27 maxL = max(maxL, len); 28 len = 0; 29 } 30 } 31 maxL = max(maxL, len); 32 33 return maxL;