跳到主要内容

32. [✔][H]最长有效括号

给你一个只包含 '('')' 的字符串,找出最长有效(格式正确且连续)括号子串的长度。

示例 1:

输入:s = "(()"
输出:2
解释:最长有效括号子串是 "()"

示例 2:

输入:s = ")()())"
输出:4
解释:最长有效括号子串是 "()()"

示例 3:

输入:s = ""
输出:0

提示:

  • 0 <= s.length <= 3 * 104
  • s[i]'('')'

题解:

逻辑梳理:


以s = ")()())"为例,stack=[],dp=[].

i=0时,")"字符,dp[1]=0, dp = [empty,0,empty,empty,empty,empty,empty]

i=1时,"("字符,dp[2]=0,dp = [empty,0,0,empty,empty,empty,empty],stack=[1]

i=2时,")"字符,leftIndex=1, stack=[], len=2-1+dp[1]+1=2, dp[3]=2,dp = [empty,0,0,2,empty,empty,empty]

i=3时,"("字符,dp[4]=0,dp = [empty,0,0,2,0,empty,empty],stack=[3]

i=4时,")"字符,leftIndex=3, stack=[], len=4-3+dp[3]+1=4, dp[5]=4,dp = [empty,0,0,2,0,4,empty]

i=5时,")"字符,dp[6]=0,dp = [empty,0,0,2,0,4,0]

以上可以看出,stack存储的是未匹配的做括号的索引,当遇到右括号时会pop出去。

dp[i]存储的是以 s[i-1] 结尾的最长合法括号子串长度,所以dp[0]=empty。

i - leftindex + dp[leftindex] + 1;这个计算公式表示(i-leftindex+1)为当前合法字符串长度,再加上之前dp[leftindex]也就是s[0,leftindex-1]中合法字符串长度的和

/*
* @lc app=leetcode.cn id=32 lang=typescript
*
* [32] 最长有效括号
*/

// @lc code=start
function longestValidParentheses(s: string): number {
let stack: number[] = [];//stack只是记录最近的(括号的索引值
// dp[i] 的定义:记录以 s[i-1] 结尾的最长合法括号子串长度
let dp: number[] = [];// 每次都会记录一个dp[i],无论是0还是一个具体其他数字


for (let i = 0; i < s.length; i++) {
const char = s[i];

// 左括号
if (char === "(") {
stack.push(i);
dp[i + 1] = 0;
} else { //右括号
if (stack.length > 0) {
// 配对的左括号对应索引
let leftindex = stack.pop()!;
// 以这个右括号结尾的最长子串长度
let len = i - leftindex + dp[leftindex] + 1;
dp[i + 1] = len;
} else {
// 孤零零一个右括号
dp[i + 1] = 0;
}
}
}


let res = 0;
for (let i = 0; i < dp.length; i++) {
res = Math.max(dp[i], res);
}
return res;
};
// @lc code=end