题目
给出一个长度为 n 的,仅包含字符 '(' 和 ')' 的字符串,计算最长的格式正确的括号子串的长度。
- 例1: 对于字符串 "(()" 来说,最长的格式正确的子串是 "()" ,长度为 2 .
- 例2:对于字符串 ")()())" , 来说, 最长的格式正确的子串是 "()()" ,长度为 4 .
字符串长度:0≤n≤5∗10^5
要求时间复杂度 O(n) ,空间复杂度 O(n).
示例1
输入:
"(()"
返回值:
2
示例2
输入:
"(())"
返回值:
4
思路:动态规划
- step 1:用dp[i]表示以下标为i的字符为结束点的最长合法括号长度。
- step 2:很明显知道左括号不能做结尾,因此左括号都是dp[i]=0。
-
step 3:遍历字符串,因为第一位不管是左括号还是右括号dp数组都是0,因此跳过,后续只查看右括号的情况,右括号有两种情况:
情况一:
如图所示,左括号隔壁是右括号,那么合法括号需要增加2,可能是这一对括号之前的基础上加,也可能这一对就是起点,因此转移公式为:dp[i] = (i >= 2 ? dp[i - 2] : 0) + 2。
情况二:
如图所示,与该右括号匹配的左括号不在自己旁边,而是它前一个合法序列之前,因此通过下标减去它前一个的合法序列长度即可得到最前面匹配的左括号,因此转移公式为:dp[i] = dp[i - 1] + ((i - dp[i - 1]) >= 2 ? dp[i - dp[i - 1] - 2] : 0) + 2。
-
step 4:每次检查完维护最大值即可。
代码
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
* @param s string字符串
* @return int整型
*/
public int longestValidParentheses (String s) {
//1.创建dp表
//dp[i]表示以下标为i的字符为结束点的最长合法括号长度
int[] dp = new int[s.length()];
//2.初始化为0,省略
int maxLen = 0;
//3.填表
//第一位不管是左括号还是右括号都是0,因此不用管
for (int i = 1; i < s.length(); i++) {
//取到左括号记为0,右括号才合法
if (s.charAt(i) == ')') {
if (s.charAt(i - 1) == '(') { //如果该右括号前一位就是左括号,计数+
dp[i] = (i >= 2 ? dp[i - 2] : 0) + 2;
} else if (i - dp[i - 1] > 0 && s.charAt(i - dp[i - 1] - 1) == '(') { //找到这一段连续合法括号序列前第一个左括号做匹配
dp[i] = dp[i - 1] + ((i - dp[i - 1]) >= 2 ? dp[i - dp[i - 1] - 2] : 0) + 2;
}
//维护最大值
maxLen = Math.max(maxLen, dp[i]);
}
}
//4.返回值
return maxLen;
}
}