Longest Valid Parentheses
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 存储没有匹配的括号的下标。遍历每个字符 s[i]:
- 若栈顶的括号可以匹配当前括号,计算此时的有效匹配长度:如果 stack 大小为 1,那么从
s[0] 至 s[i] 的所有括号都匹配上了,长度为 i+1;否则有效匹配长度仅为 i−stack.peek()。 - 若栈顶的括号和当前括号不匹配,则把当前括号入栈,作为未匹配的上一个 index。
代码如下:
class Solution {
public:
int longestValidParentheses(string s) {
stack<int> posStack; // 使用 stack 存储没有匹配的括号的下标
int len = s.size(), maxLen;
for (int i = 0; i < len; ++i) {
if (s[i] == '(') {
// 遇到 '(' 直接入栈,和栈顶的括号不匹配
posStack.push(i);
}
else {
if (!posStack.empty() && s[posStack.top()] == '(') {
// 栈顶的括号可以匹配当前括号
posStack.pop();
// posStack.empty() ? i + 1 : i - posStack.top() 计算了当前有效匹配长度
maxLen = max(posStack.empty() ? i + 1 : i - posStack.top(), maxLen);
}
else {
// 栈顶的括号和当前括号不匹配
posStack.push(i);
}
}
}
return maxLen;
}
};
思路二:使用动态规划(Dynamic Programming)求解。
维护一个长度为s.length()
的一维数组dp[]
。 dp[i]
表示从s[i]
到s[s.length() - 1]
包含s[i]
的最长的有效匹配括号子串的长度。则dp[]
存在如下的递推关系:
- dp[s.length()−1]=0;
- i 从
s.length()−2 到 0 逆向求dp[] ,并记录其最大值。
- 若 s[i]=′(′,则在 s 中从
i 开始到 s.length()−1 计算 dp[i] 的值:
- 在 s 中跳过从
i+1 开始的有效括号匹配子串,查看下一个字符,即下标为 j=i+1+dp[i+1] 的元素。若 j 没有越界,并且s[j]==′)′ ,则 s[i...j] 为有效括号匹配,dp[i]=dp[i+1]+2 - 在求出 s[i...j] 的有效匹配长度之后,若 j+1 没有越界,则 dp[i] 的值还要加上从 j+1 开始的最长有效匹配,即 dp[j+1]。
- 在 s 中跳过从
- 若 s[i]==′)′,则 dp[i]=0。
- 若 s[i]=′(′,则在 s 中从
代码如下:
class Solution {
public:
int longestValidParentheses(string s) {
int len = s.size(), maxLen = 0;
int dp[len]; // dp[]
memset(dp, 0, sizeof(dp)); // 初始化为0
for (int i = len - 2; i >= 0; --i) {
// 只对左括号处理,右括号在数组中存储为0
if (s[i] == '(') {
// 计算与当前左括号匹配的右括号的位置,可能存在也可能不存在
int j = i + 1 + dp[i+1];
if (j < len && s[j] == ')') {
/* 找到了相匹配的右括号,当前数组中存储的最长长度是它后一
* 个位置加2,后一个位置可能存储长度是0。
*/
dp[i] = dp[i+1] + 2;
if (j + 1 < len) {
/* 是连接两个子匹配的关键步骤。在j的后面可能已经存在连
* 续的匹配,要记得加上。dp[j+1]存储了以j+1开始的匹配
*/
dp[i] += dp[j+1];
}
if (dp[i] > maxLen) maxLen = dp[i]; //更新最长长度
}
}
}
return maxLen;
}
};