
/**
validLen[]:有效长度,validLen[i]代表,以下标i结尾时连续有效括号长度
初始时全部默认初始化为0,且i = 0时,必定不存在有效括号,从1开始
动态规划:
情况一:()()
以下标1结尾:validLen[1]--> if(s[1] == ')') --> if(s[1 - 1] == '(') --> validLen[1] == 2
以下标2结尾:validLen[2]--> if(s[2] == ')') --> if(s[2 - 1] == '(') --> validLen[2] == 2 (长度为3最多就一个括号)
以下标3结尾:validLen[3]--> if(s[3] == ')') --> if(s[3 - 1] == '(') --> validLen[3] == 2 + validLen[3 - 2]
.......
以下标i结尾:validLen[i]--> if(s[i] == ')') --> if(s[i - 1] == '(') --> validLen[i] == 2 + validLen[i - 2]
即,当前[i-1,i]-->[(,)]可组成一个有效括号长度为2,还要加上以i - 2结尾的有效括号长度(注,当i >= 3时才成立,只有长度为4时才有可能存在两对及以上括号)
情况二:(())
以下标i结尾:validLen[i]--> if(s[i] == ')') --> if(s[i - 1] == ')') --> if(s[i - validLen[i - 1] - 1] == '('])
--> validLen[i] = 2 + validLen[i - 1] + validLen[i - validLen[i - 1] - 2]
即最外层的(2) + 中间嵌套的(validLen[i - 1]) + 最外层左边有可能的(validLen[i - validLen[i - 1] - 2])
栈:
定义一个布尔数组Marks记录括号是否合法,与一个栈
遍历字符串,如果遇到左括号则压入栈中(下标),如果遇到右括号则弹出元素
将弹出的元素与当前遍历到的元素对应下标在Marks设置为true,若无元素可弹出,则将Marks对应位置设置为false
遍历布尔数组,最长连续的true即为最长连续有效括号
*/
java
class Solution {
/**
validLen[]:有效长度,validLen[i]代表,以下标i结尾时连续有效括号长度
初始时全部默认初始化为0,且i = 0时,必定不存在有效括号,从1开始
动态规划:
情况一:()()
以下标1结尾:validLen[1]--> if(s[1] == ')') --> if(s[1 - 1] == '(') --> validLen[1] == 2
以下标2结尾:validLen[2]--> if(s[2] == ')') --> if(s[2 - 1] == '(') --> validLen[2] == 2 (长度为3最多就一个括号)
以下标3结尾:validLen[3]--> if(s[3] == ')') --> if(s[3 - 1] == '(') --> validLen[3] == 2 + validLen[3 - 2]
.......
以下标i结尾:validLen[i]--> if(s[i] == ')') --> if(s[i - 1] == '(') --> validLen[i] == 2 + validLen[i - 2]
即,当前[i-1,i]-->[(,)]可组成一个有效括号长度为2,还要加上以i - 2结尾的有效括号长度(注,当i >= 3时才成立,只有长度为4时才有可能存在两对及以上括号)
情况二:(())
以下标i结尾:validLen[i]--> if(s[i] == ')') --> if(s[i - 1] == ')') --> if(s[i - validLen[i - 1] - 1] == '('])
--> validLen[i] = 2 + validLen[i - 1] + validLen[i - validLen[i - 1] - 2]
即最外层的(2) + 中间嵌套的(validLen[i - 1]) + 最外层左边有可能的(validLen[i - validLen[i - 1] - 2])
栈:
定义一个布尔数组Marks记录括号是否合法,与一个栈
遍历字符串,如果遇到左括号则压入栈中(下标),如果遇到右括号则弹出元素
将弹出的元素与当前遍历到的元素对应下标在Marks设置为true,若无元素可弹出,则将Marks对应位置设置为false
遍历布尔数组,最长连续的true即为最长连续有效括号
*/
public int longestValidParentheses(String s) {
//动态规划
//return DP(s);
//栈
return byStack(s);
}
//栈
private int byStack(String s) {
//记录括号是否合法
boolean marks[] = new boolean[s.length()];
//双端队列模拟栈
Deque<Integer> stack = new ArrayDeque<>();
char c[] = s.toCharArray();
for(int i = 0; i < c.length; i++) {
//左括号入栈
if(c[i] == '(') {
stack.push(i);
}
//右括号弹出栈顶元素
else {
if(!stack.isEmpty()) { //marks默认初始化为false,为空不用处理
int index = stack.pop();
marks[index] = true;
marks[i] = true;
}
}
}
//遍历marks,得出最长连续括号
int maxLen = 0;
int temp = 0;
for(int i = 0; i < marks.length; i++) {
if(marks[i]) {
temp++;
maxLen = Math.max(maxLen,temp);
} else {
temp = 0;
}
}
return maxLen;
}
//动态规划
private int DP(String s) {
//默认初始化全为0
int validLen[] = new int[s.length()];
//遍历过程中迭代最长有效值
int maxLen = 0;
//以0结尾不可能存在有效括号,从1开始即可
for(int i = 1; i < s.length(); i++) {
if(s.charAt(i) == ')') {
if(s.charAt(i - 1) == '(') {
if(i >= 3) { //长度大于等于4才可能出现两对及以上有效括号
validLen[i] = 2 + validLen[i - 2];
} else { //长度小于4,最多一对有效括号
validLen[i] = 2;
}
}
//情况二 嵌套
else if(s.charAt(i - 1) == ')') {
//中间嵌套了n个括号,与最外层匹配的只能在i - validLen[i - 1] - 1处;validLen[i - 1]代表嵌套的n个括号的长度
if(i - validLen[i - 1] - 1 >= 0 && s.charAt(i - validLen[i - 1] - 1)== '(') {
//外层 + 中间嵌套的
validLen[i] = 2 + validLen[i - 1];
//若整体左侧还有有效括号,还需要加上左侧的 例:()()((()))
if(i - validLen[i - 1] - 2 >= 0) {
validLen[i] += validLen[i - validLen[i - 1] - 2];//i - validLen[i - 1] - 1(嵌套结构整体) 再 - 1,嵌套结构整体左侧
}
}
}
}
maxLen = Math.max(maxLen,validLen[i]);
}
return maxLen;
}
}