持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第4天,点击查看活动详情
最长有效括号
给你一个只包含 '(' 和 ')' 的字符串s,找出最长有效(格式正确且连续)括号子串的长度。
解析
刚接触该题目时,我的想法使用栈结构来解决的,但是总有几种特殊情况过不了,于是后来我尝试了动态规划。
在开始解析前我们要明确一个观念,不是因为'('后面有一个')'才形成有效括号,而是')'前刚好有一个'('才形成有效括号。
明确该概念后,我们开始使用动态规划解题。每次用动态规划,先要搞清楚几点:
- 数组是一维的还是二维的?
- 横坐标和纵坐标分别代表着什么?
- 数组中存储的数据有什么意义?
这一题中,我们使用一维数组,每个下标代表对应字符串s的下标,数组中存储的数据代表 -- 以该下标为结尾的最长有效括号的长度。
明确这几点后开始构思,我们可以拿一个例子来进行构想:
输入: s = ")()())"
输出: 4
解释: 最长有效括号子串是 "()()"
对于下标0来说,作为开头是不可能构成有效括号的,默认为0,所以我们从下标1开始。
对于下标1,它的前一个字符是')',所以不构成有效括号,因此以它为结尾的最长有效括号长度为0。
| 字符串 | ) | ( | ) | ( | ) | ) |
|---|---|---|---|---|---|---|
| 下标 | 0 | 1 | 2 | 3 | 4 | 5 |
| 最长有效括号长度 | 0 | 0 |
对于下标2,它的前一个字符是'(',所以能构成有效括号,因此以它为结尾的最长有效括号长度可能为2,此时我们还要查看这对已经配对的有效括号前还是否连着其他有效括号,方法是查看当前下标i 减去当前下标对应的有效括号的长度2,得到下标0,再用2与0相加得到最终长度2。
| 字符串 | ) | ( | ) | ( | ) | ) |
|---|---|---|---|---|---|---|
| 下标 | 0 | 1 | 2 | 3 | 4 | 5 |
| 最长有效括号长度 | 0 | 0 | 2 |
对于下标3,它的前一个字符是')',所以不构成有效括号,因此以它为结尾的最长有效括号长度为0。
| 字符串 | ) | ( | ) | ( | ) | ) |
|---|---|---|---|---|---|---|
| 下标 | 0 | 1 | 2 | 3 | 4 | 5 |
| 最长有效括号长度 | 0 | 0 | 2 | 0 |
对于下标4来说,它的前一个字符是'(',所以能构成有效括号,我们如法炮制,找到下标2,发现这两有效括号可以连在一起,因此以下标4为结尾的最长有效括号长度为4。
| 字符串 | ) | ( | ) | ( | ) | ) |
|---|---|---|---|---|---|---|
| 下标 | 0 | 1 | 2 | 3 | 4 | 5 |
| 最长有效括号长度 | 0 | 0 | 2 | 0 | 4 |
对于下标5来说,它的前一个字符是')',所以不构成有效括号,因此以它为结尾的最长有效括号长度为0。
| 字符串 | ) | ( | ) | ( | ) | ) |
|---|---|---|---|---|---|---|
| 下标 | 0 | 1 | 2 | 3 | 4 | 5 |
| 最长有效括号长度 | 0 | 0 | 2 | 0 | 4 | 0 |
由动态规划的表格得知,最长有效括号的长度为4,字符为s[i-4+1,i]。
代码
class Solution {
public int longestValidParentheses(String s) {
int[] dp = new int[s.length()];
if(s.length() < 2){
return 0;
}
if(s.charAt(1)==')'){
if(s.charAt(0)=='('){
dp[1] = 2;
}
}
int max = dp[1];
for (int i = 2; i < s.length(); i++) {
if (s.charAt(i) == ')') {
if (s.charAt(i - 1) == '(') {
//贴贴
dp[i] = dp[i - 2] + 2;
} else {
//大肠包小肠
int local = i - dp[i - 1] - 1;
if(local >= 0 && s.charAt(local) == '('){
dp[i] = dp[i - 1] + 2;
if(local != 0){
dp[i] += dp[local - 1];
}
}
}
max = Math.max(dp[i],max);
}
}
return max;
}
}