32. 最长有效括号
是一个dp的题目,设dp[i]表示以i结尾的最长匹配串的长度。接着我们就可以考虑两种情况:
- s.charAt(i)=='(' 这种情况显然dp[i]=0
- s.charAt(i)==')' 为不失一般性,设当前串为((...)(...)
- 具体分析下,就可以得到此时要匹配的左括号应该位于一连串已经匹配的串之前,显然这个字符的位置是i-1-dp[i-1]
- 于是就可以得到dp[i]=dp[i-1]+2+dp[i-1-dp[i-1]-1]
- 但我们要注意初始化情况,包括越界考虑的问题。我们主要的假设是判定两段连续都存在,于是我们需要在写的时候解决是否两段都存在的问题。
下面给出两种处理,一种是利用判断,以及扩充dp数组来求解,第二种是利用逻辑表达式来简化处理。
第一种:
public int longestValidParentheses(String s) {
if (s == null || s.length() <= 1) return 0;
int[] dp = new int[s.length() + 1];
int ans = 0;
for (int i = 1; i < s.length(); i++) {
if (s.charAt(i) == ')') {
if (i - dp[i] - 1 >= 0 && s.charAt(i - dp[i] - 1) == '(') dp[i + 1] = dp[i] + 2 + dp[i - dp[i] - 1];
}
ans = Math.max(ans, dp[i + 1]);
}
return ans;
}
第二种:比较推荐这一种,因为当逻辑和建模相等时候,会比较好写以及方便debug,逻辑表达式蛮有用的。
public int longestValidParentheses(String s) {
if (s == null || s.length() <= 1) return 0;
int[] dp = new int[s.length()];
int ans = 0;
for (int i = 1; i < s.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 + ((i - 2 - dp[i - 1]) >= 0 ? dp[i - 2 - dp[i - 1]] : 0);
}
ans = Math.max(ans, dp[i]);
}
return ans;
}