给你一个只包含
'('
和')'
的字符串,找出最长有效(格式正确且连续)括号子串的长度。
解法1 辅助栈
思路
这题做过类似的,有效括号判断(LeetCode 20),当时是遇到 '('
就入栈,遇到 ')'
就出栈匹配。
而这题需要入栈字符吗?我们要求的是有效括号的长度,需要用到索引,跟字符没有关系,所以我们应该入栈索引。
栈的目的是记录上一个没有被匹配的索引,每次 ')'
匹配完,只需要弹出一次,并用栈顶的新值计算长度。栈初始化有 -1
是为了设置一个基准,防止上来就出现 ')'
匹配。栈空说明基准失效,要重新 push
当前 i
。
代码
function longestValidParentheses(s: string): number {
let result = 0;
if (!s.length) return result;
const stk = [-1];
for (let i = 0; i < s.length; i++) {
if (s[i] === '(') {
stk.push(i);
} else {
stk.pop(); // 弹出一个 '(' 的索引 或 -1
if (stk.length === 0) {
// 没有未匹配的左括号了,更新基准位置
stk.push(i);
} else {
// 当前合法长度是 i - stk[stk.length - 1]
result = Math.max(result, i - stk[stk.length - 1]);
}
}
}
return result;
};
时空复杂度
时间复杂度:O(n)
空间复杂度:O(n)
解法2 动态规划
思路
状态定义: dp[i]
为以 s[i]
结尾的最长有效括号子串的长度,dp数组初始化的时候都为 0
只需要考虑当前是 ')'
的情况,第一种就是前一个刚好为 '('
,这样匹配了一对。
而如果前一个是 ')'
,但和前面更早的 s[i - dp[i - 1] - 1] === '('
配对。
代码
function longestValidParentheses(s: string): number {
let result = 0;
if (!s.length) return result;
const dp = new Array(s.length).fill(0);
for (let i = 1; i < s.length; i++) {
if (s[i] === ')' && s[i - 1] === '(') {
dp[i] = (i >= 2 ? dp[i - 2] : 0) + 2;
} else if (s[i] === ')' && s[i - 1] === ')' && s[i - dp[i - 1] - 1] === '(') {
dp[i] = dp[i - 1] + 2 + (i - dp[i - 1] >= 2 ? dp[i - dp[i - 1] - 2] : 0);
}
result = Math.max(result, dp[i]);
}
return result;
};
时空复杂度
时间复杂度:O(n)
空间复杂度:O(n)