[100天算法】-最长有效括号(day 38)

题目描述

给定一个只包含 '(' 和 ')' 的字符串,找出最长的包含有效括号的子串的长度。示例 1:输入: "(()"
输出: 2
解释: 最长有效括号子串为 "()"
示例 2:输入: ")()())"
输出: 4
解释: 最长有效括号子串为 "()()"来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-valid-parentheses
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

方法 1:滑动窗口

思路

  1. 首先最短的有效括号字符串就是一对括号 (),那我们可以先在字符串 s 中找到这样一对括号。

  2. 然后,把这对括号作为一个滑动窗口的中心,分别向左右两侧扩大滑动窗口,窗口内是有效括号。

  3. 当滑动窗口不能再扩大时,把当前窗口的左右边界记录下来,然后,从这个窗口的右边界开始,重复步骤 1 到 3,直到字符串遍历结束。

  4. 等等,还漏了一种情况。当我们在扩大滑动窗口的时候,如果碰到了另一个窗口的边界,那这两个窗口加起来也是一个有效括号字符串。所以,我们得把这两个窗口作为新的滑动窗口中心,然后向两侧扩大窗口。

  5. 因为我们是从左往右遍历字符串,所以窗口相碰的情况只有一种,就是当前窗口的左边界碰到了前一个窗口的右边界,我们只要判断这种情况就行。

图解

代码

JavaScript Code

/*** @param {string} s* @return {number}*/
var longestValidParentheses = function (s) {const expand = (s, l, r) => {while (s[l - 1] === '(' && s[r + 1] === ')') {l--;r++;}return [l, r];};const map = {};let l = 0,r = 0,max = 0;while (true) {// 以括号对为中心l = s.indexOf('()', r);if (l === -1) break;r = l + 1;// 向左右两边不断扩大滑动窗口[l, r] = expand(s, l, r);// 当窗口扩大到最大时,// 如果当前窗口的左边界刚好挨着前一个窗口的右边界,那么,// 合并这两个窗口,再以这个新合并的窗口为中心,向两侧扩大滑动窗口while (l - 1 in map) {[l, r] = expand(s, map[l - 1], r);}// 记录当前窗口的左右边界,key 是窗口右边界,value 是窗口左边界map[r] = l;// 更新最大窗口max = Math.max(max, r - l + 1);}return max;
};

复杂度分析

  • 时间复杂度:$O(n)$,n 为字符串的长度。
  • 空间复杂度:$O(n)$,n 为字符串的长度。

方法 2:动态规划

思路

我们可以用一个一维数组 dp 来记录 以当前坐标为结尾的有效括号字符串的长度是多少 这个状态。

关键是,怎么找到当前坐标的状态 dp[i] 跟 i 之前坐标的状态的依赖关系。

  • 如果当前坐标 i 是一个左括号 '(',很明显有效字符串不会以左括号为结尾,所以这个状态是 0;
  • 如果当前坐标 i 是一个右括号 ')',那么:
    • 如果它前一个 i - 1 是 '(',它们可以组成一对儿,那么 dp[i] 至少是 2
    • 如果它前一个 i - 1 是 ')',虽然它们不能成对儿,但是,')' 说明它可能是某个有效字符串的结尾,那我们就得检查这个坐标 i - 1 的状态了:
      • 如果 dp[i-1] 是 0,那就没戏了,dp[i] 也只能是 0 了
      • 如果 dp[i-1] > 0,那么,i 的前面有一段有效括号字符串,那只要判断这段字符串前面的那个字符是不是 ( 就好了,如果是,dp[i] = dp[i-1] + 2,如果不是,dp[i] = 0
    • 等等,还没有结束,如果到了这里,dp[i] 大于 0 的话,还有一种情况,跟滑动窗口解法里面的一样,它的左边可能还有一段紧挨着的有效括号字符串,所以我们得把这段字符串的长度也加到 dp[i] 中。

图解

代码

JavaScript Code

/*** @param {string} s* @return {number}*/
var longestValidParentheses = function (s) {// 状态:以当前字符结尾的字符串,最长的有效括号长度是多大const dp = Array(s.length).fill(0);for (let i = 1; i < s.length; i++) {// 有效括号只能是以 ')' 结尾的// 所以,以 '(' 结尾的字符串,最长有效括号长度就是 0,不用管if (s[i] === ')') {// 遇到 ')' 时,往左边去找跟它匹配的 '(',如果存在,那么有效长度在 dp[i - 1] 基础上加 2// dp[i - 1] 是以 s[i - 1] 结尾的字符串的最长有效括号长度,设它为 k,// 也就是 [i - k, i - 1] 这段是有效括号字符串,// 如果这段字符串前面的那个字符 s[i - k - 1] 是 '(' 的话,那么有效长度加 2if (i - dp[i - 1] - 1 >= 0 && s[i - dp[i - 1] - 1] === '(') {dp[i] = dp[i - 1] + 2;// 如果匹配到的 '(' 前面还有有效长度的话,也加上if (i - dp[i - 1] - 2 > 0) {dp[i] += dp[i - dp[i - 1] - 2];}}}}return Math.max(...dp, 0);
};

复杂度分析

  • 时间复杂度:$O(n)$,n 为字符串的长度。
  • 空间复杂度:$O(n)$,n 为字符串的长度。

方法 3:栈

思路

用一个栈来检查括号的有效性,用一个数组 valid 来记录匹配括号对的位置。

  • 栈的用法跟20.有效括号里的一样,不过入栈的不是 (,而是它们的下标。
  • 在遍历过程中,如果碰到 ),就从栈中弹出一个元素,这个元素就是 ) 对应的 ( 的下标。
  • 接着我们在 valid 中这两个下标对应的位置做个标识 1,说明这里找到了一对有效括号。
  • 等遍历结束之后,在 valid 中找到连续最长的 1 序列。

代码

JavaScript Code

/*** @param {string} s* @return {number}*/
var longestValidParentheses = function (s) {const valid = Array(s.length).fill(0);const stack = [];for (let i = 0; i < s.length; i++) {if (s[i] === '(') stack.push(i);if (s[i] === ')' && stack.length > 0) {// Mark the open and close indices as 1 in valid.valid[i] = 1;valid[stack.pop()] = 1;}}// Find longest sequence of 1s.let count = 0,max = 0;for (let v of valid) {v && count++;v || (count = 0);count > max && (max = count);}return max;
};

复杂度分析

  • 时间复杂度:$O(n)$,n 为字符串的长度。
  • 空间复杂度:$O(n)$,n 为字符串的长度。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/117410.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Day07 Stream流递归Map集合Collections可变参数

Stream 也叫Stream流&#xff0c;是Jdk8开始新增的一套API (java.util.stream.*)&#xff0c;可以用于操作集合或者数组的数据。 Stream流大量的结合了Lambda的语法风格来编程&#xff0c;提供了一种更加强大&#xff0c;更加简单的方式操作 public class Demo1 {public stati…

面试算法40:矩阵中的最大矩形

题目 请在一个由0、1组成的矩阵中找出最大的只包含1的矩形并输出它的面积。例如&#xff0c;在图6.6的矩阵中&#xff0c;最大的只包含1的矩阵如阴影部分所示&#xff0c;它的面积是6。 分析 直方图是由排列在同一基线上的相邻柱子组成的图形。由于题目要求矩形中只包含数字…

SpringCloud微服务 【实用篇】| 认识微服务

目录 一&#xff1a;认识微服务 1. 微服务框架介绍 2. 服务架构演变 3. 微服务技术对比 4. SpringCloud 图书推荐&#xff1a;《巧用ChatGPT快速提高职场晋升力》 一&#xff1a;认识微服务 本课程学习于黑马&#xff0c;会通过分层次学习&#xff0c;分为三部分去讲解微…

数据与视图的完美契合:Vue响应式的交织魅力

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

springboo单机多线程高并发防止重复消费的redis方案

springboo单机多线程高并发防止重复消费的redis方案 仅提供方案与测试。 想法&#xff1a;第一次收到userCode时&#xff0c;检查是否在redis中有&#xff0c;如果有&#xff0c;就表明已经消费了&#xff0c;返回抢单失败&#xff1b;否则&#xff0c;就去消费&#xff0c;顺…

从REST到GraphQL:升级你的Apollo体验

前言 「作者主页」&#xff1a;雪碧有白泡泡 「个人网站」&#xff1a;雪碧的个人网站 「推荐专栏」&#xff1a; ★java一站式服务 ★ ★ React从入门到精通★ ★前端炫酷代码分享 ★ ★ 从0到英雄&#xff0c;vue成神之路★ ★ uniapp-从构建到提升★ ★ 从0到英雄&#xff…

Qt之实现支持多选的QCombobox

一.效果 1.点击下拉列表的复选框区域 2.点击下拉列表的非复选框区域 二.实现 QHCustomComboBox.h #ifndef QHCUSTOMCOMBOBOX_H #define QHCUSTOMCOMBOBOX_H#include <QLineEdit> #include <QListWidget> #include <QCheckBox> #include <QComboBox>…

R语言生物群落(生态)数据统计分析与绘图

R 语言作的开源、自由、免费等特点使其广泛应用于生物群落数据统计分析。生物群落数据多样而复杂&#xff0c;涉及众多统计分析方法。以生物群落数据分析中的最常用的统计方法回归和混合效应模型、多元统计分析技术及结构方程等数量分析方法为主线&#xff0c;通过多个来自经典…

计算机算法分析与设计(14)---贪心算法(会场安排问题和最优服务次序问题)

文章目录 一、会场安排问题1.1 问题描述1.2 思路分析1.3 例题分析1.4 代码编写 二、最优服务次序问题2.1 问题描述2.2 思路分析2.3 代码编写 一、会场安排问题 1.1 问题描述 假设在足够多的会场里安排一批活动&#xff0c;并希望使用尽可能少的会场。设计一个有效的贪心算法进…

十八、字符串(3)

本章概要 正则表达式 基础创建正则表达式量词CharSequencePattern 和 Matcherfinde()组&#xff08;Groups&#xff09;start() 和 end()Pattern 标记split()替换操作reset()正则表达式与 Java I/0 正则表达式 很久之前&#xff0c;_正则表达式_就已经整合到标准 Unix 工具…

python网络爬虫实例

目录 1、访问百度 2、输入单词百度翻译 3、豆瓣电影排行榜 4、豆瓣电影top250 5、下载美女壁纸 1、访问百度 from urllib.request import urlopen url"http://www.baidu.com" respurlopen(url)with open("mybaidu.html",mode"w") as f:f.wr…

ilr normalize isometric log-ratio transformation

visium_heart/st_snRNAseq/05_colocalization/create_niches_ct.R at 5b30c7e497e06688a8448afd8d069d2fa70ebcd2 saezlab/visium_heart (github.com) 更多内容&#xff0c;关注微信&#xff1a;生信小博士 The ILR (Isometric Log-Ratio) transformation is used in the anal…

Maven 生命周期clean default size含义

clean 负责清理工作&#xff0c;清理上一次项目构建产生的一些文件&#xff0c;如编译后的字节码文件&#xff0c;打包后的jar包文件 default 整一个项目构建的核心工作&#xff0c;如编译&#xff0c;测试&#xff0c;打包&#xff0c;安装&#xff0c;部署等等 size 生成报告…

CLion使用SSH远程连接Linux服务器

最近要一直用实验室的服务器写Linux下的C代码, 本来一直用VScode(SSH)连接服务器, 但是我以前还是用JetBrains的IDE用的多, 毕竟他家的IDE代码提示和功能在某些细节上更加丰富。所以这次我使用了Clion里的远程连接(同样也是SSH工具)连接上了我的服务器, 实现了和VScode上同样的…

【FPGA零基础学习之旅#17】搭建串口收发与储存双口RAM系统

&#x1f389;欢迎来到FPGA专栏~搭建串口收发与储存双口RAM系统 ☆* o(≧▽≦)o *☆嗨~我是小夏与酒&#x1f379; ✨博客主页&#xff1a;小夏与酒的博客 &#x1f388;该系列文章专栏&#xff1a;FPGA学习之旅 文章作者技术和水平有限&#xff0c;如果文中出现错误&#xff0…

Linux 开机启动一条PHP命令

当你开机的时候要自动的启动一条PHP命令场景&#xff1a;比如webman 你需要手动启动项目进程 你可以这样操作 流程&#xff1a; 1、准备好你要执行的命令 2、将命令写入一个服务文件 3、开机自启这个服务 实例&#xff1a; 1、比如这个命令 /usr/local/php/bin/php /ho…

Docker:创建主从复制的Redis集群

一、Redis集群 在实际项目里&#xff0c;一般不会简单地只在一台服务器上部署Redis服务器&#xff0c;因为单台Redis服务器不能满足高并发的压力&#xff0c;另外如果该服务器或Redis服务器失效&#xff0c;整个系统就可能崩溃。项目里一般会用主从复制的模式来提升性能&#x…

CouchDB简单入门

CouchDB 1.curl命令 RESTful 新增&#xff1a;POST请求修改&#xff1a;PUT请求删除&#xff1a;DELETE请求查找&#xff1a;GET请求 查看数据库有哪些 curl -X GET http://admin:123456localhost:5984/_all_dbsadmin: 用户名 123456:改成自己密码 创建数据库 curl -X PU…

《语音优先》智能语音技术驱动的交互界面设计与语音机器人设计(译者序)...

“言为心声,语为心境”&#xff0c;语言与对话是我们沟通与协作的重要方式。而智能语音技术是一种基于人工智能和自然语言处理技术的语音交互技术。它可以通过语音识别技术将用户的语音指令转换为文本&#xff0c;然后通过自然语言处理技术对文本进行分析和理解&#xff0c;最终…

WIN11+OPENCV4.8 编译及下载失败处理方法

1. 基础准备 1. 下载Opencv和Contrib库 Opencv&#xff1a;Releases opencv/opencv GitHub Contrib&#xff1a;Tags opencv/opencv_contrib GitHub 2. 安装Visual Studio 或 MinGW64 MinGW&#xff1a;Tags opencv/opencv_contrib GitHub 这里安装1.12.0 MinGW 。 以…