给你一个只包含 '('
和 ')'
的字符串,找出最长有效(格式正确且连续)括号子串的长度。
示例 1:
输入: s = "(()"
输出: 2
解释: 最长有效括号子串是 "()"
示例 2:
输入: s = ")()())"
输出: 4
解释: 最长有效括号子串是 "()()
示例 3:
输入: s = ""
输出: 0
题解:
/**
* @param {string} s
* @return {number}
*/
// 方法一:栈
var longestValidParentheses = function (s) {
let len = 0;
const stack = [];
// 栈内预设初始值
stack.push(-1)
for (let i = 0; i < s.length; i++) {
let val = s[i]
// 当遇到左括号是入栈下标
if (val == '(') {
stack.push(i)
} else {
// 当遇到右括号是入栈下标
stack.pop()
// 判断当栈不为空时 取当前下标与栈顶元素差值为有效长度
// 当栈顶为空时当前位置入栈
if (stack.length) {
let cur = i - stack[stack.length - 1]
len = Math.max(len, cur)
} else {
stack.push(i)
}
}
}
return len
};
// 方法二:左右遍历
var longestValidParentheses = function (s) {
let left = 0, right = 0, manLen = 0;
// 一次从左向右遍历,一次从右向左遍历是为了互补操作
// 从左向右遍历 当左括号大于右括号时
// 例如:'(()'没办法计算出来有效长度
for (let i = 0; i < s.length; i++) {
let val = s[i]
if (val == '(') {
left++
} else {
right++
}
if (left == right) {
manLen = Math.max(manLen, 2 * left)
} else if (right > left) { // 避免')('情况
left = 0;
right = 0;
}
}
left = 0;
right = 0;
// 从右向左遍历 解决左括号大于右括号时获取有效长度
// 同时不能处理'())'这种情况
for (let i = s.length - 1; i >= 0; i--) {
let val = s[i]
if (val == '(') {
left++
} else {
right++
}
if (left == right) {
manLen = Math.max(manLen, 2 * left)
} else if (left > right) {
left = 0;
right = 0;
}
}
return manLen
}
动态规划
思路:dp[i]表示以i结尾的最长有效括号的长度,分为4种情况,看图
复杂度:时间复杂度O(n),n是字符串的长度,总共遍历1次。空间复杂度O(n),即dp数组的空间
作者:xiaochen1024
// 方法三:动态规划 dp
const longestValidParentheses = (s) => {
let maxLen = 0;
const len = s.length;
const dp = new Array(len).fill(0);
for (let i = 1; i < len; i++) {
// 以')'结尾的字符才有效
if (s[i] == ')') {
// 如果前一个位置是'(' 则能与当前字符形成有效括号
if (s[i - 1] == '(') {
// 如果前2个位置还有字符串
if (i - 2 >= 0) {
//当前状态等于 当前匹配的2个字符 加上 前两个位置匹配最长字符长度
dp[i] = dp[i - 2] + 2;
} else {// 如果前2个位置没有字符串
dp[i] = 2;// 当前状态等于 当前匹配的2个字符
}
// 以i-1结尾的有效字符在向前看1个位置 如果是'('
// 则能与当前字符形成有效括号
} else if (s[i - dp[i - 1] - 1] == '(') {
// 以i-1结尾的有效字符在向前看2个位置 如果>=于0
if (i - dp[i - 1] - 2 >= 0) {
// 当前状态 =
// 以i-1结尾的有效字符长度 +
// 当前匹配2个有效括号 +
// 以i - dp[i - 1] - 2结尾的有效字符长度
dp[i] = dp[i - 1] + 2 + dp[i - dp[i - 1] - 2];
} else {
// 以i-1结尾的有效字符在向前看2个位置 如果<于0
// 当前状态=以i-1结尾的有效字符长度 + 当前匹配2个有效括号
dp[i] = dp[i - 1] + 2;
}
}
}
maxLen = Math.max(maxLen, dp[i]);
}
return maxLen;
};
来源:力扣(LeetCode)
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。