这是我参与11月更文挑战的第28天,活动详情查看:2021最后一次更文挑战
leetcode 最长有效括号
给你一个只包含 '(' 和 ')' 的字符串,找出最长有效(格式正确且连续)括号子串的长度。
示例 1:
输入:s = "(()"
输出:2
解释:最长有效括号子串是 "()"
示例 2:
输入:s = ")()())"
输出:4
解释:最长有效括号子串是 "()()"
示例 3:
输入:s = ""
输出:0
解题: 可以先想办法获取每一个有效括号的长度,最后取最大长度即可。对于字符串s来说,如果存在多个有效括号组合,那这些括号组合肯定不会是连续的,中间由一些不是有效括号的括号分隔,那就可以使用栈来判断,将每个括号在字符串的下标存到栈里面,就可以用栈来匹配括号,然后根据两个括号的下标可以确定这个有效括号的长度。首先遍历字符串,当遇到左括号时,将其在字符串的下标放入栈中,遇到右括号时,然后就考虑弹出栈元素进行匹配,但如果栈为空时,说明当前右括号没有可以匹配的左括号,那就要将当前右括号下标放入栈中。如果栈不空,那就取出栈顶元素可以匹配的左括号的下标,那当前右括号下标减去取出左括号下标就是当前获取的有效括号长度。重复这个操作最后取出最大的一个长度即可。
class Solution {
public int longestValidParentheses(String s) {
int maxLen = 0;
Deque<Integer> stack = new LinkedList<Integer>();
stack.push(-1);
for (int i = 0; i < s.length(); i++) {
// 左括号入栈
if (s.charAt(i) == '(') {
stack.push(i);
} else {
// 右括号出栈
stack.pop();
if (stack.isEmpty()) {
// 空栈就加入这个括号的下标
stack.push(i);
} else {
// 获取最大长度
maxLen = Math.max(maxLen, i - stack.peek());
}
}
}
return maxLen;
}
}
或者用两个变量left、right,分别记录下左括号和右括号的数量,先从左到右遍历字符串,left、right从0开始记录左右括号的数量,当左右括号数量相等时就可以获取当前有效括号的长度,然后用个maxLen变量记录下获取到的最大长度。当右括号数量大于左括号数量时,不可能为有效括号,需要把left、right的数量重置为0。当左括号数量一直都是大于右括号数量时,就没法算出有效括号长度了,所以需要再从右到左变量一遍来算有效括号的长度,同样的left、right从0开始,分别记录下左括号和右括号的数量,相等时获取有效括号长度,但左括号数量大于右括号数量时就没法匹配了,需要重置为0重新开始计数。
class Solution {
public int longestValidParentheses(String s) {
int left = 0;
int right = 0;
int maxlen = 0;
// 从左到右遍历
for (int i = 0; i < s.length(); i++) {
// 统计左右括号的数量
if (s.charAt(i) == '(') {
left++;
} else {
right++;
}
// 如果相等获取最大长度
if (left == right) {
maxlen = Math.max(maxlen, 2 * right);
} else if (right > left) {
// 需要重新开始统计
left = right = 0;
}
}
// 从右到左再遍历一次
left = right = 0;
for (int i = s.length() - 1; i >= 0; i--) {
// 统计左右括号的数量
if (s.charAt(i) == '(') {
left++;
} else {
right++;
}
// 如果相等获取最大长度
if (left == right) {
maxlen = Math.max(maxlen, 2 * left);
} else if (left > right) {
// 需要重新开始统计
left = right = 0;
}
}
return maxlen;
}
}