给你一个只包含 '(' 和 ')' 的字符串,找出最长有效(格式正确且连续)括号子串的长度。
示例 1:
输入:s = "(()" | |
输出:2 | |
解释:最长有效括号子串是 "()" |
示例 2:
输入:s = ")()())" | |
输出:4 | |
解释:最长有效括号子串是 "()()" |
示例 3:
输入:s = "" | |
输出:0 |
提示:
0 <= s.length <= 3 * 104 | |
s[i] 为 '(' 或 ')' |
解法一:栈
/** | |
* 栈 | |
* | |
* 我们始终保持栈底元素为当前已经遍历过的元素中「最后一个没有被匹配的右括号的下标」,这样的做法主要是考虑了边界条件的处理,栈里其他元素维护左括号的下标: | |
* | |
* 对于遇到的每个 '(' ,我们将它的下标放入栈中 | |
* 对于遇到的每个 ')' ,我们先弹出栈顶元素表示匹配了当前右括号: | |
* 如果栈为空,说明当前的右括号为没有被匹配的右括号,我们将其下标放入栈中来更新我们之前提到的「最后一个没有被匹配的右括号的下标」 | |
* 如果栈不为空,当前右括号的下标减去栈顶元素即为「以该右括号为结尾的最长有效括号的长度」 | |
* | |
*/ | |
public int longestValidParentheses2(String s) { | |
Stack<Integer> stack = new Stack<>(); | |
// 如果一开始栈为空,第一个字符为左括号的时候我们会将其放入栈中, | |
// 这样就不满足提及的「最后一个没有被匹配的右括号的下标」,为了保持统一, | |
// 我们在一开始的时候往栈中放入一个值为 -1 的元素。 | |
stack.push(-1); | |
int max = 0; | |
char[] array = s.toCharArray(); | |
for (int i = 0; i < s.length(); i++){ | |
// 当为左括号时,将当前进栈 | |
if (array[i] == '('){ | |
stack.push(i); | |
}else { | |
// 当为右括号时出栈 | |
stack.pop(); | |
// 如果栈为空,将当前右括号位置入栈 | |
if (stack.empty()){ | |
stack.push(i); | |
}else { | |
// 否则由当前位置 - 栈顶元素 | |
max = Math.max(max, i - stack.peek()); | |
} | |
} | |
} | |
return max; | |
} |
解法二:正向逆向结合
/** | |
* 正向逆向结合 | |
* | |
* 我们利用两个计数器 left 和 right 。首先,我们从左到右遍历字符串, | |
* 对于遇到的每个‘(’,我们增加 left 计数器,对于遇到的每个‘)’ , | |
* 我们增加 right 计数器。每当 left 计数器与 right 计数器相等时,我们计算当前有效字符串的长度, | |
* 并且记录目前为止找到的最长子字符串。当 right 计数器比 left 计数器大时,我们将 left 和 right 计数器同时变回 0。 | |
* | |
*/ | |
public int longestValidParentheses1(String s) { | |
int length = s.length(); | |
int left = 0, right = 0, max = 0; | |
// 从左往右跑 | |
for (int i = 0; i < length; i++){ | |
// 统计左括号和右括号的数量 | |
if (s.charAt(i) == '('){ | |
left++; | |
}else { | |
right++; | |
} | |
// 当两个括号数量一致时,统计最大数量 | |
// 当右括号大于左括号数量时,重置 | |
if (left == right){ | |
max = Math.max(max, right * 2); | |
}else if (right > left){ | |
left = right = 0; | |
} | |
} | |
// 从右往左跑 | |
left = right = 0; | |
for (int i = length - 1; i >= 0; i--){ | |
// 统计左括号和右括号数量 | |
if (s.charAt(i) == '('){ | |
left++; | |
}else { | |
right++; | |
} | |
// 当两个括号数量一致时,统计最大数量 | |
// 当左括号大于右括号数量时,重置 | |
if (left == right){ | |
max = Math.max(max, left * 2); | |
}else if (left > right){ | |
left = right = 0; | |
} | |
} | |
return max; | |
} |
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/longest-valid-parentheses