一、题目描述
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.
给定一个字符串,只有字符'('和')',找到最长的有效匹配括号子串长度。
二、思路
思路一:栈实现
一般来说,括号匹配最容易想到的做法是栈,所以一开始采用了栈的做法。
思路是:如果只是求括号匹配,不需要连续,那直接使用栈的结构就可以匹配,遇到左括号入栈,遇到右括号就从栈中匹配推出一个左括号匹配即可。举个例子,s = (((()(((),这个字符串有两处括号匹配,但是本题要求的是最长子串,所以要求是连在一起的,所以上述字符串就只能算一处匹配,最长的长度是2.我采用的解决方法是定义一个布尔数组,数组大小和字符串长度一样,记录每一个位置是否匹配,然后到最后统计连续true的长度,就可以得到最长的匹配子串啦。算法描述如下:
声明一个栈st,一个布尔数组isMatch,循环遍历字符串s,循环遍历是i表示第i个字符:
1. 当遇到一个左括号时,将左括号所在的字符位置i入栈;
2. 否则,如果栈不为空,那弹出栈顶的值top,并把isMatch[top]和isMatch[i]置为true。
循环结束后,统计最长的连续1的个数。
这个思路是直接简单且快速的,然后我注意到的是这道题的tag是动态规划(DP),所以我考虑了一下动态规划的方法来解决这道题。
思路二:动态规划
动态规划解决的话,首先要定义子问题。子问题dp[i]表示第i个字符处的最长匹配子串的长度。作为一个最长的匹配子串,肯定是以')'结束,因此,所有以'('结束的位置的dp值直接都是0,只需要考虑以')'结束的情况。有两种情况:
1.当右括号之前是左括号,即()的情况:
当s[i] = ')'且s[i-1]是’(’,那么dp[i] = dp[i-2] + 2;
2.当右括号之前也是右括号,即))的情况,这有可能是(()),也可能是((()())):
s[i - dp[i-1] - 1]表示跳过前面已匹配好的位置,如果这个位置是’(’,那么
dp[i] = dp[i−1] + dp[i−dp[i−1]−2] + 2
三、代码
int longestValidParentheses_stack(string s) {
stack<int> st;
int res = 0;
if (s.length() == 0)
return 0;
bool isMatch[s.length()];
memset(isMatch, false, sizeof(isMatch));
for (int i = 0; i < s.length(); i++) {
if (s[i] == '(')
st.push(i);
else {
if (!st.empty()) {
isMatch[st.top()] = true;
isMatch[i] = true;
st.pop();
}
}
}
int temp = 0;
for (int i = 0; i < s.length(); i++) {
if (isMatch[i])
temp++;
else
temp = 0;
if (res < temp)
res = temp;
}
return res;
}
思路二代码:
int longestValidParentheses_dp(string s) {
int res = 0;
int dp[s.length()];
memset(dp, 0, sizeof(dp));
for (int i = 1; i < s.length(); i++) {
if (s[i] == ')') {
if (s[i - 1] == '(')
dp[i] = (i >= 2 ? dp[i - 2] : 0) + 2;
else {
if (i - dp[i-1] > 0 && ((s[i - dp[i - 1] - 1]) == '(')) {
dp[i] = dp[i - 1] + (i - dp[i-1] >= 2 ? dp[i - dp[i - 1] - 2]:0) + 2;
}
}
res = max(res, dp[i]);
}
}
return res;
}