32. 最长有效括号

2023-10-27

32. 最长有效括号

题目描述

给你一个只包含 '('')' 的字符串,找出最长有效(格式正确且连续)括号子串的长度。

示例1:

输入:s = "(()"
输出:2
解释:最长有效括号子串是 "()"

示例2:

输入:s = ")()())"
输出:4
解释:最长有效括号子串是 "()()"

示例3:

输入:s = ""
输出:0

提示:

  • 0 ≤ s . l e n g t h ≤ 3 ∗ 1 0 4 0 \le s.length \le 3 * 10^4 0s.length3104
  • s[i]'('')'

题解:
法一:

动态规划,设 f[i] 表示 s[0..i] 中必须以 s[i] 结尾的最长有效括号子串的长度。分以下情况讨论:

  • f[0] = 0,只含有一个字符肯定不是有效括号子串

  • 从左到右遍历 s

    1. 如果 s[i] == '('f[i] = 0 ,有效括号子串必定以 ) 结尾
    2. 如果 s[i] == ')' ,因为 f[i - 1] 是以 s[i - 1] 结尾的最长有效括号子串的长度,所以如果 i - f[i - 1] - 1 位置上是 ( ,就能与 s[i] 凑出一对有效括号,此时 f[i] = f[i - 1] + 2 。但是还有一种情况,比如 "()(())" ,在遍历到最后一个 ) 时,通过上述找到的最长有效括号子串是 "(())" ,但是前面的 "()" 部分可以跟 "(())" 结合构成更长的合法括号子串,所以还应该加上 f[i - f[i - 1] - 2]
  • 遍历过程保留最大值就是结果

时间复杂度: O ( n ) O(n) O(n)

额外空间复杂度: O ( n ) O(n) O(n)

法一代码:

class Solution {
public:
    int longestValidParentheses(string s) {
        int n = s.length();
        if ( n < 2 ) return 0;
        vector<int> f( n, 0 );
        int pre, ret = 0;
        for ( int i = 1; i < n; ++i ) {
            if ( s[i] == '(' ) continue;
            pre = i - f[i - 1] - 1;
            if ( pre >= 0 && s[pre] == '(' )
                f[i] = f[i - 1] + 2 + ( pre > 0 ? f[pre - 1] : 0 );
            ret = max( ret, f[i] );
        }
        return ret;
    }
};
/*
时间:0ms,击败:100.00%
内存:7.2MB,击败:78.30%
*/

法二:

使用栈模拟。

考虑到一个合法的括号序列有两个特征:

  1. 左右括号数量相等
  2. 任意一个括号序列的前缀,左括号数量 >= 右括号数量

我们可以根据第二个特征,将括号序列划分成一个个小区间,每个区间以右括号结尾且其前面是合法的括号子串,比如 “(()))())” 可以划分成 “(()))” 和 “())” 两段,并且不会出现合法括号子串跨越多段的情况(感兴趣可自行证明)。这样的话,我们就可以使用栈来操作,栈中保存的是合法括号子串前一个位置,开始为-1。

从左往右遍历整个字符串,具体操作流程:

  • 如果 s[i]( ,则入栈 i

  • 如果 s[i]) ,则弹出栈顶元素(表示右括号匹配到左括号),继续判断:

    1. 如果栈为空,说明没有与之匹配的左括号,也就是说,s[i] 是当前合法括号子串的右端点,所以将 i 入栈
    2. 如果栈非空,那么 i - stk.top() 就是当前右括号对应的合法括号子串长度

时间复杂度: O ( n ) O(n) O(n)

额外空间复杂度: O ( n ) O(n) O(n)

法二代码:

class Solution {
public:
    int longestValidParentheses(string s) {
        int n = s.length();
        if ( n < 2 ) return 0;
        stack<int> stk;
        stk.push( -1 );
        int ret = 0;
        for ( int i = 0; s[i]; ++i ) {
            if ( s[i] == '(' ) stk.push( i );
            else {
                stk.pop();
                if ( stk.empty() ) stk.push( i );
                else ret = max( ret, i - stk.top() );
            }
        }
        return ret;
    }
};
/*
时间:0ms,击败:100.00%
内存:7.2MB,击败:81.77%
*/
法三:

贪心,两次扫描。

( 当作 1, 把 ) 当作 -1 ,一个合法的括号序列其前缀和的值肯定为零,并且任何时刻,一个合法的括号序列,其前缀和不可能小于零(法二中第二条特征)。

于是可以从前往后扫描,pre 表示合法括号子串的前一个位置,初始值为 -1 ,变量 cnt 记录前缀和,如果是左括号,则cnt += 1 ,否则的话,则 cnt -= 1。若 cnt > 0 ,说明缺少右括号,pre 不动;若 cnt < 0 ,说明缺少左括号,说明 s[pre +1...i] 这个区间左括号数量小于右括号数量,非法,需要抛弃该区间,令 pre = i, cnt = 0 ;若 cnt == 0 ,说明当前是一个合法的括号子串,则更新最大答案。

注意:上面保证了:任何时刻左括号数量不小于右括号数量,所以 “)))(((” 这种情况是不会被当做合法括号序列的。

但是,从左往右遍历对于 “((())” 这种情况是无法解决的,可以从右往左遍历,然后将上述条件取反,即可处理所有情况。

时间复杂度: O ( n ) O(n) O(n)

额外空间复杂度: O ( 1 ) O(1) O(1)

法三代码:

class Solution {
public:
    int longestValidParentheses(string s) {
        int n = s.length();
        if ( n < 2 ) return 0;
        int cnt = 0, pre = -1, ret = 0;
        for ( int i = 0; s[i]; ++i ) {
            if ( s[i] == '(' ) ++cnt;
            else --cnt;
            if ( cnt < 0 ) pre = i, cnt = 0;
            else if ( !cnt ) ret = max( ret, i - pre );
        }
        pre = n, cnt = 0;
        for ( int i = n - 1; i >= 0; --i ) {
            if ( s[i] == ')' ) ++cnt;
            else --cnt;
            if ( cnt < 0 ) pre = i, cnt = 0;
            else if ( !cnt ) ret = max( ret, pre - i );
        }
        return ret;
    }
};
/*
时间:4ms,击败:91.21%
内存:6.6MB,击败:99.62%
*/
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

32. 最长有效括号 的相关文章

  • java3D 第三章 java3D基本图形类详解

    第三章 java 3D基本图形功能 java 3D基本图形功能 java 3D场景式管理 SimpleUniverse类及其方法 ViewingPlatform类及方法 包的关系 Shape3D类及方法 Appearance类及方法 Bra
  • 大数据技术——Scala语言基础

    Scala语言概述 计算机的缘起 数学家阿隆佐 邱奇 Alonzo Church 设计了 入演算 这是一套用于研究函数定义 函数应用和递归的形式系统 入演算被视为最小的通用程序设计语言 入演算的通用性就体现在 任何一个可计算函数都能用这种形
  • 对于stm32,初学者用库函数好还是直接对寄存器操作比较好

    在stm32教学光盘的A里 有两个开发指南 一个是库函数版本 一个是寄存器版本 那么问题来了 作为一个初学者 我应该用库函数好还是直接对寄存器操作比较好 为此我搜集了一些资料 找到了一些可以借鉴的文章 首先 两个都是C语言 从51过渡过来的
  • PBFT代码实现

    本篇文章主要是PBFT共识的简单实现 其中有许多地方都做了简化 PBFT的原理已在上篇文章中描述过 如果对PBFT的原理不太清晰的的可以进行查看 文章地址 共识算法学习总结 代码实现的主要功能有 通过客户端添加区块 使用libp2p的mdn

随机推荐

  • CVTE笔试面试经验分享(硬件)—2020秋招

    秋招流程 投简历 在线笔试 技术面试一 技术面试二 综合面试 投简历 简历是直接在CVTE的校招网上投递的 然后可以选择面试城市和笔试时间 在线笔试 简历筛选通过后就会通知进行线上的笔试 笔试结果各个岗位不同等待的也不同 硬件笔试都是基础
  • 【Linux】基本指令(一)

    目录 一 ls指令 1 不指定目录 ls 2 指定目录 ls huangchao 3 加选项 ls l 4 加选项 ls a 5 选项组合 ls l a 6 选项 指定文件夹 ls l a huangchao 7 ls 指令总结 二 mkd
  • Opencascade安装教程(Visual Studio 2017)

    之前尝试了一次Visual Studio 2019 Opencascade7 5 0的编译 编译成功了 但是在Qt中使用的时候一堆错误没有解决 加之之前的项目需要 所以卸载了VS2019 改安装了VS2017 如果不想找太多错误 不妨可以安
  • Python实现淘宝商品数据爬取——静态网页爬虫(仅供学习,切勿无限制爬取)

    一 关于淘宝网 淘宝网是亚太地区较大的网络零售 商圈 由阿里巴巴集团在2003年5月创立 淘宝网是中国深受欢迎的网购零售平台 拥有近5亿的注册用户数 每天有超过6000万的固定访客 同时每天的在线商品数已经超过了8亿件 平均每分钟售出4 8
  • modelsim do文件简介及仿真波形分析注意事项

    目录 前言 Modelsim指令介绍 步骤一 创建run wave do 步骤二 打开Modelsim 步骤三 do run wave do 步骤4 run sim bat 补充介绍 参考 前言 本文对 do文件进行整理介绍 并在后文引用
  • 简单四边形不等式优化dp(上)

    这里只讨论简单的二维四边形不等式优化dp 和简单的广义决策单调性板子 下文中 优于 一般指的是 不劣于 请自行分辨 四边形不等式 四边形不等式定义为 位于整数集合上的二元函数 f x y f
  • sklearn中主成分分析PCA参数解释

    主成分分析一般用于数据降维 在应用主成分分析包scikit learn时注意以下四点 1 用pca components 可以获取特征向量 且特征向量为行向量 例如W pca components 0 或W pca components 0
  • Python如何生成词云(详细分析)

    前言 今天教大家用wrodcloud模块来生成词云 我读取了一篇小说并生成了词云 先看一下效果图 效果图一 效果图二 根据效果图分析的还是比较准确的 小说中的主人公就是 程理 所以出现次数最多 图中有两种模式 一种是默认的模式 另一种是自己
  • 【SpringMvc】从Servlet的HttpServlet到SpringMVC的DispathServlet到Springboot的RequestMapping

    1 0 众所周知 一个http请求到我们服务器 web容器 tomcat jetty servlet 就会约定俗成去访问webapp路径下的web xml配置文件 首先读取的是两个节点 listener 和 context param 监听
  • 自动化测试-selenium+python3+HTMLTestRunner

    案例介绍 使用selenium框架测试并输出测试报告 一 准备工作 1 编辑器 pycharm 2 安装selenium first step second step 3 导入HTMLTestRunner 用来生成测试报告的 注意 pyth
  • 细数6种垃圾回收器的区别, 快进来看看有没有你要用的

    文章目录 前言 一 垃圾回收算法 1 复制算法 2 标记 清除算法 3 标记 整理算法 4 分代算法 二 Serial收集器 三 Parallel Scavenge收集器 四 ParNew收集器 五 CMS收集器 1 GC流程 2 CMS的
  • stm32 USB CDC 不接电脑无程序一直在USB中断问题

    前些时间基于STM32CUBE 工具做了个用STM32F103的USB 接口 枚举成CDC的项目 接上电脑程序功能正常 但是在不接电脑时 程序一直在USB中断中 下在给大家分享一下我的解决方法 首先是在 stm32f1xx hal pcd
  • asp: AJAX Database

  • Python爬虫进阶:使用Scrapy库进行数据提取和处理

    在我们的初级教程中 我们介绍了如何使用Scrapy创建和运行一个简单的爬虫 在这篇文章中 我们将深入了解Scrapy的强大功能 学习如何使用Scrapy提取和处理数据 一 数据提取 Selectors和Item 在Scrapy中 提取数据主
  • python之UI自动化框架测试126邮箱(数据驱动)

    项目地址 https pan baidu com s 18XVd3IB SIQJygxUVdbuLA密码 74cm 目录和包介绍 Data目录 存放执行项目用例所需的数据文件 excel Conf目录 包含所有获取页面元素的定位表达式文件
  • python class函数解释

    init 是Python中的构造函数 构造函数用于初始化类的内部状态 为类的属性设置默认值 两个下划线开头的函数是声明该属性为私有 不能在类的外部被使用或访问 init 函数 方法 支持带参数类的初始化 也可为声明该类的属性 类中的变量 i
  • RuntimeError: Input type (torch.FloatTensor) and weight type (torch.cuda.FloatTensor) should be the

    RuntimeError Input type torch FloatTensor and weight type torch cuda FloatTensor should be the same or input should be a
  • IDEA的使用和快捷键

    从刚开始Eclipse到IDEA的不顺手 一点一点习惯上IDEA的使用 可能回去使用Eclipse估计会用不惯了 毕竟IDEA自带了很多工具maven git等工具 还有下边的一些窗口用着也还不错 大概记录一下自己在使用IDEA的过程和工作
  • 毕业项目SSM框架配置文件之applicationContext.xml

    applicationContext xml
  • 32. 最长有效括号

    32 最长有效括号 题目描述 给你一个只包含 和 的字符串 找出最长有效 格式正确且连续 括号子串的长度 示例1 输入 s 输出 2 解释 最长有效括号子串是 示例2 输入 s 输出 4 解释 最长有效括号子串是 示例3 输入 s 输出 0