题目
Given a string containing just the characters '('
and ')'
, find the length of the longest valid (well-formed) parentheses substring.
Example 1:1
2
3Input: "(()"
Output: 2
Explanation: The longest valid parentheses substring is "()"
Example 2:1
2
3Input: ")()())"
Output: 4
Explanation: The longest valid parentheses substring is "()()"
题解
- 题目的意思比较简单,给出一个只由左括号和右括号组成的字符串,求出有效的括号匹配最长长度
方法 1 - 利用stack
- 利用数据结构
stack
完成,整个过程中stack
的第一个元素为当前已遍历的不匹配括号串的最后一个')'
的下标或者-1
,其余在stack
中存储的是字符'('
的下标,参见阐述的步骤即可指定。使用stack
的FILO
的特性完成判断字符是否括号是否匹配以及计算有效匹配括号的长度 - 步骤
- 首先将
-1
推进stack
中 - 遍历字符串,对于字符进行不同的处理
'('
, 直接将其下标推入栈中-stack.push(i)
')'
,首先弹出栈顶元素-stack.pop()
。接下来的步骤需要划分两种情况进行:
- 如果当前栈中已经为空,即证明当前匹配的串已经无效,因为
')'
数目大于'('
的数目,无法有效匹配括号,此时不做关于最长匹配的记录,只把当前下标推入栈中(当前')'
的下标即为已遍历的不匹配括号串的最后一个')'
的下标) - 如果当前栈不为空,则证明目前匹配的串依旧有效,则更新一下最长匹配长度 -
num = max(num, i - myStack.top())
- 首先将
- 实现代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22// stack
class Solution {
public:
int longestValidParentheses(string s) {
stack<int> myStack;
myStack.push(-1);
int num = 0;
for(int i = 0; i < s.size(); ++i) {
if(s[i] == '(')
myStack.push(i);
else {
myStack.pop();
if(myStack.empty())
myStack.push(i);
else {
num = max(num, i - myStack.top());
}
}
}
return num;
}
};
方法 2 - 动态规划
- 思路
- 括号匹配的时候,遇到
')'
才可能成功匹配上。因此,使用一个数组num
记录每个)
最长有效匹配的长度。 - 当前检索到
')'
有两种情况- 情况1:
"...()..."
- 这种至少匹配的长度是2,但是可能连着之前也是有可能满足的,例如
"...()()..."
这种情况,因此需要考虑连着已匹配的-(i >= 2 ? num[i-2] : 0)
- 转移方程:
num[i] = (i >= 2 ? num[i-2] : 0) + 2;
- 这种至少匹配的长度是2,但是可能连着之前也是有可能满足的,例如
- 情况2:
"...))..."
- 这种情况的匹配与前一个
')'
相关,如果前面是有效匹配的,则需要检查s[i-num[i-1]-1] == '('
(条件:i >= num[i-1] + 1
),即需要考虑"...((...))..."
的情况。同时,还需要考虑前面是否可以与有效匹配的串连接起来,例如"...()((...))..."
,因此还需要考虑连着已匹配的-i >= num[i-1] + 2 ? num[i - num[i-1] - 2] : 0
- 转移方程:
num[i] = num[i-1] + 2 + (i >= num[i-1] + 2 ? num[i - num[i-1] - 2] : 0)
- 这种情况的匹配与前一个
- 情况1:
- 括号匹配的时候,遇到
- 实现代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23// dp
class Solution {
public:
int longestValidParentheses(string s) {
if(!s.size()) return 0;
int maxNum = 0;
int num[s.size()] = {0};
for(int i = 1; i < s.size(); ++i){
if(s[i] == ')' && s[i-1] == '(') {
// "...()..."
num[i] = (i >= 2 ? num[i-2] : 0) + 2;
}
else if(s[i] == ')' && s[i-1] == ')' && i >= num[i-1] + 1 && s[i-num[i-1]-1] == '(') {
// "...((...))..."
num[i] = num[i-1] + 2 + (i >= num[i-1] + 2 ? num[i - num[i-1] - 2] : 0);
}
maxNum = max(maxNum, num[i]);
}
return maxNum;
}
};