一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第 9 天,点击查看活动详情。
最长有效括号
给你一个只包含 '(' 和 ')' 的字符串,找出最长有效(格式正确且连续)括号子串的长度。
示例 1:
输入:s = "(()"
输出:2
解释:最长有效括号子串是 "()"
示例 2:
输入:s = ")()())"
输出:4
解释:最长有效括号子串是 "()()"
示例 3:
输入:s = ""
输出:0
提示:
0 <= s.length <= 3 *s[i]为'('或')'
思路分析
- 真是羞愧,每次遇到这种题目想到的都是粗暴解法。第一反应就是字符串中将所有的有效括号子串罗列出来,然后取那个长度最长的,但是毫无意外,最终又超时了
o(╥﹏╥)o; - 那么只能选择别的方式了。这种类型的题目,可以使用动态规划的方法来解决;
- 定义一个以
s.length+1为长度,0为内容的res数组,其中res[i]表示 以s[i-1]结尾的最长有效括号的子串长度; - 那么,接下来遍历
s,如果遇到左括号'('记录索引压入栈,并且 res[i+1] = 0,因为左括号不可能是有效括号子串的结尾; - 遇到右括号
')',若栈内有值,则先找到配对的左括号的索引,即弹出栈顶,并且记录以这个右括号为结尾的最长子串长度为1 + i - left + res[left];否则没有找到匹配的左括号,即res[i+1] = 0; - 将
res降序排列,返回res[0]即可。
AC 代码
/**
* @param {string} s
* @return {number}
*/
var longestValidParentheses = function(s) {
let stack = [];
let res = new Array(s.length + 1).fill(0)
for (let i = 0; i < s.length; i++) {
if (s.charAt(i) == "(") {
stack.push(i);
res[i + 1] = 0;
} else {
if (stack.length) {
let left = stack.pop();
let len = 1 + i - left + res[left];
res[i + 1] = len;
} else {
res[i + 1] = 0;
}
}
}
return res.sort((a, b) => b - a)[0]
};
结果:
- 执行结果: 通过
- 执行用时:148 ms, 在所有 JavaScript 提交中击败了7.34%的用户
- 内存消耗:47.8 MB, 在所有 JavaScript 提交中击败了5.02%的用户
- 通过测试用例:231 / 231