一【题目类别】
- 字符串
二【题目难度】
- 困难
三【题目编号】
- 32.最长有效括号
四【题目描述】
- 给你一个只包含 ‘(’ 和 ‘)’ 的字符串,找出最长有效(格式正确且连续)括号子串的长度。
五【题目示例】
-
示例 1:
- 输入:s = “(()”
- 输出:2
- 解释:最长有效括号子串是 “()”
-
示例 2:
- 输入:s = “)()())”
- 输出:4
- 解释:最长有效括号子串是 “()()”
-
示例 3:
- 输入:s = “”
- 输出:0
六【解题思路】
- 大多数人遇到这道题首先想到栈,但是怎么用栈去处理这个题才是难点
- 我们要先明白一个合法的括号序列需要满足的条件如下:
- 任意前缀中左括号的数量≥右括号的数量
- 整体的左右括号数量相等
- 所以我们可以利用右括号数量首次大于左括号数量的位置将原字符串分割为几部分,这每一部分都保证了左右括号数量相等,但是我们要找到其中最长的合法序列,所以说,最长有效括号一定在某一段中产生,那么我们只需要在每一段中找到最长有效括号,最终找到最大值即可
- 另外还要注意我们入栈和比较都是元素下标,这样我们才能求出长度
- 那么具体在遍历字符串的时候有两种情况:
- 遇到左括号:将下标入栈
- 遇到右括号
- 如果栈不空,说明匹配到一个合法的括号序列,将栈顶元素出栈,与当前右括号匹配
- 出栈后再判断一下栈空不空,如果栈不空,那么当前栈顶元素的下一个位置就是合法的左括号位置,我们经过计算比较大小之后存储即可,这个可以随便画一画就能明白,涉及到下标的关系
- 出栈后如果栈空,那么当前段的起始点到目前位置都是合法的序列长度,和上面进行同样的计算
- 如果栈空,说明当前的右括号是段和段之间的分割点,那么我们就要去下一段中寻找,所以更新下一段的起始位置为当前的右括号位置
- 如果栈不空,说明匹配到一个合法的括号序列,将栈顶元素出栈,与当前右括号匹配
七【题目提示】
- 0 < = s . l e n g t h < = 3 ∗ 1 0 4 0 <= s.length <= 3 * 10^4 0<=s.length<=3∗104
- s [ i ] 为 ′ ( ′ 或 ′ ) ′ s[i] 为 '(' 或 ')' s[i]为′(′或′)′
八【时间频度】
- 时间复杂度: O ( n ) O(n) O(n),其中 n n n 是字符串的长度
- 空间复杂度: O ( n ) O(n) O(n),其中 n n n 是字符串的长度
九【代码实现】
- Java语言版
package String;
import java.util.Deque;
import java.util.LinkedList;
public class p32_LongestValidParentheses {
public static void main(String[] args) {
String s = ")()())";
int res = longestValidParentheses(s);
System.out.println("res = " + res);
}
public static int longestValidParentheses(String s) {
Deque<Integer> stack = new LinkedList<Integer>();
int start = -1;
int res = 0;
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == '(') {
stack.push(i);
} else {
if (!stack.isEmpty()) {
stack.pop();
if (!stack.isEmpty()) {
res = Math.max(res, i - stack.peek());
} else {
res = Math.max(res, i - start);
}
} else {
start = i;
}
}
}
return res;
}
}
- C语言版
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
int longestValidParentheses(char * s)
{
int stack[30001] = { 0 };
int top = -1;
int res = 0;
int start = -1;
for (int i = 0; i < strlen(s); i++)
{
if (s[i] == '(')
{
stack[++top] = i;
}
else
{
if (top != -1)
{
top--;
if (top != -1)
{
res = fmax(res, i - stack[top]);
}
else
{
res = fmax(res, i - start);
}
}
else
{
start = i;
}
}
}
return res;
}
/*主函数省略*/
十【提交结果】
-
Java语言版
-
C语言版