给定一个只包含 ‘(’ 和 ‘)’ 的字符串,找出最长的包含有效括号的子串的长度。
示例 1:
输入: "(()"
输出: 2
解释: 最长有效括号子串为 "()"
示例 2:
输入: ")()())"
输出: 4
解释: 最长有效括号子串为 "()()"
有两种解答方式。
第一种,滑动窗口。
对字符串进行括号闭合验证,记录最值。
然后再进行一次对称变换,进行验证,两次取最值,就是字符串的最长有效括号长度
之所以进行一次对称,对称不会改变括号闭合的子串,但可以帮助我们转换一些干扰地方。
class Solution {
public int longestValidParentheses(String s) {
if (s == null || s.equals(""))
return 0;
int max = 0;
char[] chs = s.toCharArray();
max = Math.max(max, len(chs));
// 置反
for (int i = 0; i < chs.length; ++i) {
if (chs[i] == ')') {
chs[i] = '(';
} else {
chs[i] = ')';
}
}
// 倒序
for (int i = 0; i < chs.length / 2; ++i) {
char temp = chs[i];
chs[i] = chs[chs.length - i - 1];
chs[chs.length - i - 1] = temp;
}
// 对称后再验证
max = Math.max(max, len(chs));
return max;
}
// 闭合验证,并记录最大匹配长度
public int len(char[] s) {
int len = 0, complete = 0;
int l = 0, r = 0, size = s.length;
while (r < size) {
if (s[r] == ')') {
complete += 1;
} else {
complete -= 1;
}
if (complete == 0) {// 括号闭合
len = Math.max(len, r - l + 1);
r += 1;
} else if (complete > 0) {// )[l,r]不能闭合
r += 1;
l = r;
complete = 0;
} else {
r += 1;
}
}
return len;
}
}
还有一种,动态规划。
/*
* 对于dp[],i->[0,dp.len),dp[i]记录[i-dp[i],i]这个区间完成的括号闭合的长度<br>
* 而dp[i]的长度取决i-1前一个的闭合长度,还取决于新的闭合区间的前一个dp[i-dp[i]]的闭合长度<br>
* /
class Solution {
public int longestValidParentheses(String s) {
int[] dp = new int[s.length()];
int max = 0;
for (int i = 1; i < dp.length; ++i) {
if (s.charAt(i) == ')') {
if (i - 1 - dp[i - 1] >= 0 && s.charAt(i - 1 - dp[i - 1]) == '(') {
dp[i] += dp[i - 1] + 2;
}
if (i - dp[i] >= 0) {
dp[i] += dp[i - dp[i]];
}
max = Math.max(max, dp[i]);
}
}
return max;
}
}
如有纰漏,欢迎提出!