给你一个只包含 '(' 和 ')' 的字符串,找出最长有效(格式正确且连续)括号 子串 的长度。
左右括号匹配,即每个左括号都有对应的右括号将其闭合的字符串是格式正确的,比如 "(()())"。
示例 1:
输入:s = "(()"
输出:2
解释:最长有效括号子串是 "()"
示例 2:
输入:s = ")()())"
输出:4
解释:最长有效括号子串是 "()()"
示例 3:
输入:s = ""
输出:0
提示:
0 <= s.length <= 3 * 104s[i]为'('或')'
看一下题解 这个题解真是太牛逼了,这个思路是很通用的,需要好好学习总结 正常的思维是我们到第六个的时候,才会知道左括号已经匹配没有了,这时候计算就不太适合了 所以应该让第五个来计算,所以初始添加一个 -1 真是天才的设计啊
思路是理解了,但是有点绕,有没有更好的办法 绕的地方就是在于每次进入 ) 括号分支的时候,需要 pop 一次,这个 pop 有点绕,其他的还好
const longestValidParentheses = function (s) {
let max = 0;
let stack = [];
stack.push(-1);
for (let i = 0; i < s.length; i++) {
const c = s[i];
if (c === '(') {
stack.push(i);
}
else {
// 这里没有直接检测是否有 (而是直接 pop 是为了让下面的 i push进来,做到一个更换初始值 -1 的作用
stack.pop();
if (stack.length) {
const curMax = i - stack[stack.length - 1];
max = Math.max(max, curMax);
}
else {
// 充当「参照物」的右括号索引。因为:当左括号匹配光时,栈需要留一个垫底的参照物,用于计算一段连续的有效长度。
stack.push(i);
}
}
}
return max;
}理一下上述解法的思路 0. 核心还是 ) 这个 分支里面的逻辑,这里面有 pop 还有 push 操作,是先 pop 然后 push 的 也就是如果一直是 ),那么每次都会更新 最后一个 ) 的位置 如果有 stack.length 的时候,这时候说明就有 ( push进去了,这时候就可以计算当前的有效括号的长度了
- 为什么要先 stack.pop() 然后再检测 stack.length 因为stack.pop() 后,这时候使用 i - stack[stack.length - 1] 就是实际的括号长度了 比如 () 那么在stack里面就是 -1, 0,这时候i = 1的时候,因为把0 pop出去了,这时候就是i - (-1) 就是2,就是括号的实际长度了
- 如果 stack没有length了,就需要把当前的i放进去,因为这时候就需要重新开始计算了,之前的有效的括号数已经计算过了
这个是个很规矩的解法,
const longestValidParentheses = function (s) {
if (s.length === 0) {
return 0;
}
const dp = Array(s.length).fill(0);
let max = 0;
for (let i = 1; i < s.length; i++) {
if (s[i] === ')') {
if (s[i - 1] === '(') {
// 2 是一对括号的长度,i - 2 是因为当前的括号是有效括号,所以需要减去2
dp[i] = 2 + (i - 2 >= 0 ? dp[i - 2] : 0);
} else if (i - 1 >= 0 && s[i - 1] === ')') {
// dp[i - 1] 是前面正常匹配的长度,i - 长度,又因为当前的括号是有效括号,所以需要减去1, 得到前面的括号的索引
const matchIndex = i - dp[i - 1] - 1;
if (matchIndex >= 0 && s[matchIndex] === '(') {
// dp[i - 1] + 2 得到有效括号的长度,此时因为
dp[i] = dp[i - 1] + 2 + (matchIndex - 1 >= 0 ? dp[matchIndex - 1] : 0);
}
}
}
max = Math.max(max, dp[i]);
}
return max;
}
const result = longestValidParentheses("(()");
console.log(result);
const result2 = longestValidParentheses(")()())");
console.log(result2);
const result3 = longestValidParentheses("");
console.log(result3);