题目描述:
给定一个只包含 '(' 和 ')' 的字符串,找出最长的包含有效括号的子串的长度。
注意:我连续想错了两次题目意思,可以嵌套,只要左右匹配就好
今日学习:
1.察觉到异常的时候要把它揪出来想,不要忽视它
题解:
1.维护一个栈,但是栈中存的并不是左括号,而是左括号的索引,这样就可以每次都计算出子串的长度了
2.左右遍历s,计算左右括号数量是否匹配
3.这道题动规真难,没想明白,我放弃了
// 错误题解:维护一个'('栈,但是想法有一些问题,有些情况没考虑进去
var longestValidParentheses = function(s) {
let res = 0, count = 0, later = 0
let stack = []
for(i = 0; i < s.length; i++) {
if(s[i] == '(') {
stack.push(s[i])
}else {
if(stack.length == 0) {
res = Math.max(res, count)
count = 0
}else {
stack.pop()
count += 2
}
}
}
res = Math.max(res, count)
return res
}
// 还是维护栈,但是栈存的是索引而不是括号
var longestValidParentheses = function(s) {
let start = s.indexOf('(')
let end = s.lastIndexOf(')')
if(start == -1 || end == -1 || start > end) return 0
s = s.slice(start, end + 1)
// 前四行可以处理掉一些极端情况,有没有都可以
let maxLen = 0;
// 预存索引-1,方便计算长度,也是作为新的开始
const stack = [-1];
for(let i = 0; i < s.length; i++) {
const c = s[i];
if(c == '(') { // 左括号的索引入栈
stack.push(i);
continue; // 跳过,考察下一个符号
}
stack.pop(); // 遇到右括号,栈顶出栈
if(stack.length == 0) { // 栈顶因此为空
stack.push(i); // 说明该更换“断点”索引了
}else { // 计算有效的连续长度,挑战最大
maxLen = Math.max(maxLen, i - stack[stack.length - 1]);
}
}
return maxLen;
};
// 左右算括号数量的思想
var longestValidParentheses = function(s) {
let start = s.indexOf('(')
let end = s.lastIndexOf(')')
if(start == -1 || end == -1 || start > end) return 0
s = s.slice(start, end + 1)
// 前四行可以处理掉一些极端情况,有没有都可以
let left = right = 0, maxLen = 0
// 从左到右遍历
for(let i = 0; i < s.length; i++) {
//遇到左括号或者右括号,对应数量+1
if(s.charAt(i) == '(') {
left++
}else {
right++
}
// 如果数量相等,说明符合子串要求,计算当前长度
// 如果右大于左,没有继续计算长度的必要,left和right归零
if(left == right) {
maxLen = Math.max(maxLen, 2 * left)
}else if(right > left) {
left = right = 0
}
}
// 从右往左遍历,思路一致
left = right = 0
for(let i = s.length - 1; i >= 0; i--) {
if(s.charAt(i) == ')') {
right++
}else {
left++
}
if(left == right) {
maxLen = Math.max(maxLen, 2 * left)
}else if(left > right) {
left = right = 0
}
}
return maxLen
}