题目:
给你一个只包含 (
和 )
的字符串,找出最长有效(格式正确且连续)括号子串的长度
注意:该最长有效括号一定要是连续的!
思路:
- 本题可以使用
动态规划
解决,首先创建一个数组dp[]
,用来保存当前位置的最长有效子串数量 - 首先明确有效子串的条件,当前位置的字符一定为
)
,并且前面存在字符(
(Tips:不一定是紧挨着当前这个)
的),如果当前位置的字符为(
,那么该位置的dp值
一定为0。 - 因此分两种小情况,在当前位置
i
字符为)
时:- 如果前一个字符
s.charAt(i - 1)
为(
,那么当前位置上dp[i]=dp[i - 2] + 2
,也就是这一对有效子串之前的有效子串长度加上2 - 如果前一个字符
s.charAt(i - 1)
为)
,那么就要对之前的值进行判断,首先:dp[i - 1]
为前面有效子串的长度,拿当前位置减去前面有效子串的长度之后,如果找到了一个(
,说明匹配到了,也就是s.charAt(i - dp[i - 1] - 1)
为(
,然后再加上该有效子串前面位置的dp值
再加当前位置匹配到的一对括号2,就是当前位置的dp值
:dp[i] = 2 + dp[i - 1] + dp[i - dp[i - 1] - 2]
- 每经过一个位置,就更新
maxres
的值,使它保持当前时刻的最大值
- 如果前一个字符
以下为代码+注释,结合代码会好理解一点:
public int longestValidParentheses(String s) {
// 动态规划
// 设置一个变量保存整个字符串的最大有效括号长度
int maxres = 0;
int[] dp = new int[s.length()];
// 从第二个字符开始遍历,一直到最后一个,每次都与前一个比较
// 符合题目条件的情况一定是当前字符为')',前面包含'('
// 如果当前字符为'(',那么它的dp值一定为0
for(int i = 1; i < s.length(); i++){
if(s.charAt(i) == ')'){
// 1.如果前一个为'('
if(s.charAt(i - 1) == '('){
// 注意要判断索引是否越界
dp[i] = (i > 1 ? dp[i - 2] : 0) + 2;
// 2.如果前一个不为'(',但是前面仍旧存在'(',注意判断索引是否越界
}else if(i - dp[i - 1] >= 1 && s.charAt(i - dp[i - 1] - 1) == '('){
// 那么当前位置的dp值就等于2+前面一部分有效子串以及有效子串前面的有效串
dp[i] = 2 + dp[i - 1] +
(i - dp[i - 1] - 2 >= 0 ? dp[i - dp[i - 1] - 2] : 0);
}
}
maxres = Math.max(maxres, dp[i]);
}
return maxres;
}
笔者也在不断学习,如有错误,欢迎指正!