【LeetCode每日一题】——32.最长有效括号

一【题目类别】

  • 字符串

二【题目难度】

  • 困难

三【题目编号】

  • 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<=3104
  • s [ i ] 为 ′ ( ′ 或 ′ ) ′ s[i] 为 '(' 或 ')' s[i]()

八【时间频度】

  • 时间复杂度: O ( n ) O(n) O(n),其中 n n n 是字符串的长度
  • 空间复杂度: O ( n ) O(n) O(n),其中 n n n 是字符串的长度

九【代码实现】

  1. 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;
    }

}
  1. 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;
}

/*主函数省略*/

十【提交结果】

  1. Java语言版
    在这里插入图片描述

  2. C语言版
    在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IronmanJay

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值