0%

Leetcode 32 Longest Valid Parentheses

Given a string containing just the characters '(' and ')', find the length of the longest valid (well-formed) parentheses substring.

Example 1:

1
2
3
Input: "(()"
Output: 2
Explanation: The longest valid parentheses substring is "()"

Example 2:

1
2
3
Input: ")()())"
Output: 4
Explanation: The longest valid parentheses substring is "()()"

1 暴力

对于给定的i, 维护两个变量, left为左括号的数量, right为右括号的数量.

如果对于某个j, 从i到j的右括号数量大于左括号数量, 那么(i,j), (i, j+1), (i, j+2)….这些字串肯定不可能valid.

如果对于某个j, 从i到j的右括号数量等于左括号数量, 那么(i,j)就是valid, 更新maxLen = Math.max(left + right, maxLen);即可.

但是这种方法慢, 复杂度O(n^2)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Solution {
public int longestValidParentheses(String s) {
int maxLen = 0;
for(int i = 0; i < s.length(); ++i)
{
int left = 0;
int right = 0;
for(int j = i; j < s.length(); ++j)
{
if(s.charAt(j) == '(')
++left;
else if(s.charAt(j) == ')')
++right;
if(right > left)
break;
if(left == right)
{
maxLen = Math.max(left + right, maxLen);
}
}
}
return maxLen;
}
}

2 改进的括号判断

我们知道, 当从左到右遍历的时候, 如果右括号数量大于左括号数量, 后面无论括号是什么, 都不可能是一个合法的括号.

所以, i从0遍历到length - 1, 每遍历到一个括号, 都统计当前左右括号的数量.

如果left < right, 那么当前的字串肯定不可能成为valid了, 需要从s[i]后面重新统计. 所以要重新赋值left=right=0

如果left = right, 那么当前的字串是valid的, 更新maxLen = right * 2.

例如, ())()()

当遍历到第2个字符时, left = right = 1, 所以更新maxLen = 2;

当遍历到第3个字符时, left = 1, right =2, right > left, 所以left=right=0, 之前的合法括号()由于此次中断不能加入到后面的计算中.

但是这样做有个问题. 考虑()(()(), 一直有left > right, 导致遍历结束了还没有出现left == right, 自然不能更新maxLen.

解决的方法是, 从右往左再遍历一遍, 判断方式和刚才的相反, 时刻保持右括号的数量大于左括号的数量.

取两次遍历结果的最大值.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
class Solution {
public int longestValidParentheses(String s) {
int left = 0;
int right = 0;
int maxLen = 0;
for(int i = 0; i < s.length(); ++i)
{
if(s.charAt(i) == '(')
{
++left;
}
else
++right;
if(right > left)
{
right = 0;
left = 0;
}
else if(right == left)
{
maxLen = Math.max(maxLen, 2 * right);
}
}
left = 0;
right = 0;
for(int i = s.length() - 1; i > -1; --i)
{
if(s.charAt(i) == '(')
++left;
else
++right;
if(left > right)
{
right = 0;
left = 0;
}
else if(right == left)
{
maxLen = Math.max(maxLen, 2 * right);
}
}
return maxLen;
}
}

3 动态规划

参考于https://leetcode-cn.com/problems/longest-valid-parentheses/solution/zui-chang-you-xiao-gua-hao-by-leetcode-solution/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class Solution {
public int longestValidParentheses(String s) {
int[] dp = new int[s.length()];
for(int i = 0; i < s.length(); ++i)
{
if(i == 0 || s.charAt(i) == '(')
{
dp[i] = 0;
}
else
{
if(i > 0 && s.charAt(i-1) == '(')
dp[i] = (i > 1) ? dp[i-2] + 2 : 2;
else
{
int tmp = i - 1 - dp[i-1];
if(tmp >= 0 && s.charAt(tmp) == '(')
{
dp[i] = dp[i-1] + 2 + ((tmp-1 > 0) ? dp[tmp-1] : 0);
}
else
{
dp[i] = 0;
}
}
}
}
int max = 0;
for(int i : dp)
max = Math.max(max,i);
return max;
}
}