Longest Valid Parentheses
题目
Given a string containing just the characters '('
and ')'
, find the length of the longest valid (well-formed) parentheses substring.
Example 1:
Input: "(()"
Output: 2
Explanation: The longest valid parentheses substring is "()"
Example 2:
Input: ")()())"
Output: 4
Explanation: The longest valid parentheses substring is "()()"
分析
这道题的要求就是根据给出的只包含(
和)
字符串,然后求出最长的合法子串(即(
和)
能够匹配)。
解法一
我的做法是使用一个数组大小为字符串长度。遍历字符串,将(
记为-1
,)
记为1
。
然后遍历数组。数组的值如果为1
,则向左寻找第一个值为-1
的元素,然后将两者的值都置为0,表示相互匹配。
之后再次遍历数组,统计连续出现的0
的个数。返回统计结果中最大的值。
但是这种解法的时间复杂度为
O
(
n
2
)
O(n^2)
O(n2)。
解法二
其实还有一种时间复杂度为
O
(
n
)
O(n)
O(n)的解法。
具体解法是:
从左到右遍历字符串。记录(
出现的次(left
)数和)
出现的次数(right
)。当(
出现的次数等于)
出现的次数时,设置maxLength = maxLength > right* 2 ? maxLength : right * 2
。当)
出现的次数大于(
出现的次数时,设置left = right = 0
。
遍历一遍之后,会漏掉(
出现的次数大于)
,但是其子串匹配的数目大于maxLength
的情况。例如:()(()()()
,此时得到的结果为2
。
因此需要从右到左再次遍历字符串。现在时当(
括号出现的次数大于)
出现的次数时,设置left = right = 0
,和上一次遍历相反。当(
出现的次数和)
出现的次数相同时,依旧设置maxLength = maxLength > right* 2 ? maxLength : left * 2
。
这样就可以得到正确的结果了。
代码如下
解法一代码
class Solution {
public int longestValidParentheses(String s) {
int max = 0;
int[] arr = new int[s.length()];
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == '(') {
arr[i] = -1;
} else {
arr[i] = 1;
}
}
for (int i = 1; i < s.length(); i++) {
if (arr[i] == 1) {
// 可以记录上一次左括号出现的位置以加快遍历,但这里没有
int j = i;
while (--j >= 0) {
if (arr[j] == -1) {
arr[i] = 0;
arr[j] = 0;
break;
} else if (arr[j] == 1) {
break;
}
}
}
}
int tempMax = 0;
for (int i = 0; i < s.length(); i++) {
if (arr[i] == 0) {
tempMax++;
} else {
max = max > tempMax ? max : tempMax;
tempMax = 0;
}
}
max = max > tempMax ? max : tempMax;
return max;
}
}
解法二代码
class Solution {
public int longestValidParentheses(String s) {
int left = 0, right = 0, maxlength = 0;
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == '(') {
left++;
} else {
right++;
}
if (left == right) {
maxlength = Math.max(maxlength, 2 * right);
} else if (right >= left) {
left = right = 0;
}
}
left = right = 0;
for (int i = s.length() - 1; i >= 0; i--) {
if (s.charAt(i) == '(') {
left++;
} else {
right++;
}
if (left == right) {
maxlength = Math.max(maxlength, 2 * left);
} else if (left >= right) {
left = right = 0;
}
}
return maxlength;
}
}