当前位置: 首页 > news >正文

【力扣100题】50.最长有效括号

题目描述

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

左右括号匹配,即每个左括号都有对应的右括号将其闭合的字符串是格式正确的,例如"(()())"

示例:

  • 输入:s = "(()"→ 输出:2(最长有效括号子串是"()")
  • 输入:s = ")()())"→ 输出:4(最长有效括号子串是"()()")
  • 输入:s = ""→ 输出:0

解题思路总览

方法思路时间复杂度空间复杂度
动态规划dp[i]表示以第i个字符结尾的最长有效括号长度O(n)O(n)
栈中存索引,遇到)时弹出并计算长度O(n)O(n)
双指针两遍扫描,分别从左到右和从右到左处理不匹配的情况O(n)O(1)

本题采用动态规划方法。


完整代码

classSolution{public:intlongestValidParentheses(string s){intmaxLen=0,n=s.size();vector<int>dp(n,0);for(inti=1;i<n;i++){if(s[i]==')'){if(s[i-1]=='('){dp[i]=(i>=2?dp[i-2]:0)+2;}elseif(i-dp[i-1]>0&&s[i-dp[i-1]-1]=='('){dp[i]=dp[i-1]+((i-dp[i-1])>=2?dp[i-dp[i-1]-2]:0)+2;}maxLen=max(maxLen,dp[i]);}}returnmaxLen;}};

算法流程图

输入: s = ")()())" 初始化: n = 6 dp[0...5] = 0 maxLen = 0 i = 1, s[1] = '(': s[1] == ')'? 否,跳过 maxLen = 0 i = 2, s[2] = ')': s[2] == ')'? 是 s[1] == '('? 是! dp[2] = dp[0] + 2 = 0 + 2 = 2 maxLen = max(0, 2) = 2 i = 3, s[3] = '(': s[3] == ')'? 否,跳过 maxLen = 2 i = 4, s[4] = ')': s[4] == ')'? 是 s[3] == '('? 是! dp[4] = dp[2] + 2 = 2 + 2 = 4 maxLen = max(2, 4) = 4 i = 5, s[5] = ')': s[5] == ')'? 是 s[4] == '('? 否,进入 else if i - dp[4] = 5 - 4 = 1 > 0 s[1] = '('? 是! dp[5] = dp[4] + dp[0] + 2 = 4 + 0 + 2 = 6 maxLen = max(4, 6) = 6 最终 maxLen = 6 输出: 6

逐行解析

intmaxLen=0,n=s.size();

含义:maxLen记录全局最长有效括号长度,n记录字符串长度。

vector<int>dp(n,0);

含义:dp[i]表示以第i个字符结尾的最长有效括号子串长度。初始化为 0。

for(inti=1;i<n;i++)

含义:从索引 1 开始遍历(因为 dp[0] 只能是 0,不需要计算)。

if(s[i]==')')

含义:只有当当前字符是)时才可能形成有效括号。

if(s[i-1]=='(')

含义:情况一:"..."形式的最近匹配。例如"()""(...)()"

dp[i]=(i>=2?dp[i-2]:0)+2;

含义:如果是"()"形式,长度为 2 加上 dp[i-2](之前已匹配的长度)。需要判断 i-2 是否 >= 0。

elseif(i-dp[i-1]>0&&s[i-dp[i-1]-1]=='(')

含义:情况二:类似"(...])"的形式,其中...已经是有效括号段。例如"(())"中 s[3]=‘)’ 时,i-dp[i-1]=3-2=1,s[0]=‘(’,形成匹配。

dp[i]=dp[i-1]+((i-dp[i-1])>=2?dp[i-dp[i-1]-2]:0)+2;

含义:

  • dp[i - 1]:之前已经匹配的有效括号长度
  • ((i - dp[i - 1]) >= 2 ? dp[i - dp[i - 1] - 2] : 0):加上再之前的有效括号长度
  • + 2:加上当前匹配的"()"
maxLen=max(maxLen,dp[i]);

含义:更新全局最长长度。


状态转移图解

情况一:"()" 形式 i-1 i '(' ')' dp[i] = dp[i-2] + 2 情况二:"(...])" 形式 i-1 i "... ( ... ) )" ^dp[i-1] ^ i - dp[i-1] - 1 (与 i 配对的 '(' 的位置) dp[i] = dp[i-1] + dp[i - dp[i-1] - 2] + 2

复杂度分析

复杂度说明
时间复杂度O(n)只需遍历一次字符串
空间复杂度O(n)dp 数组大小为 n

面试追问 FAQ

问题答案
为什么从i = 1开始而不是i = 0因为 dp[0] 一定是 0(空字符串无法形成有效括号),从 1 开始可以减少边界判断
dp[i]为什么要定义为「以第 i 个字符结尾」?这样可以利用 dp[i-1] 的值,实现 O(1) 转移。如果是「前 i 个字符中最长」,就无法利用之前的结果
栈方法是怎么工作的?栈中存左括号的索引,遇到右括号时弹出。如果弹出后栈非空,当前长度 = i - 栈顶索引;如果栈空,当前长度 = i + 1
双指针方法的原理?从左到右扫描时,遇到不匹配的)就重置;从右到左扫描时,遇到不匹配的(就重置。两遍扫描可以覆盖所有情况
如何输出具体的最长有效括号子串?在计算 dp[i] 时记录 maxLen 对应的位置,然后从该位置向前截取 maxLen 长度的子串
进阶:如何 O(1) 空间?使用双指针方法:分别从左到右和从右到左扫描,处理不匹配的括号情况

相关题目

题号题目难度核心思路
32最长有效括号困难动态规划/栈/双指针
20有效的括号简单
22括号生成中等DFS/回溯
301删除无效的括号困难BFS/DFS

总结

要点内容
核心思想动态规划:以每个)结尾计算最长有效括号长度
状态定义dp[i]= 以第 i 个字符结尾的最长有效括号长度
状态转移情况一:"()", dp[i] = dp[i-2] + 2
状态转移情况二:"(...])", dp[i] = dp[i-1] + dp[i-dp[i-1]-2] + 2
边界处理需要判断索引是否越界
结果返回 maxLen

http://www.jsqmd.com/news/823880/

相关文章:

  • MinGW-w64完整指南:3步搭建Windows C/C++开发环境
  • 面向非完备信息环境的博弈策略智能体设计,在迷雾中博弈:面向非完备信息环境的智能体设计——从理论到PyTorch实战
  • YOLOv5实战:如何一键导出检测框的坐标、类别和置信度到TXT文件(附完整代码)
  • 从BIOS自检到图形桌面:用一张流程图和命令复盘Linux(CentOS 7)开机八大步骤
  • VirtualMonitor虚拟显示器:软件定义多屏工作空间的终极解决方案
  • 从飞思卡尔智能车大赛看嵌入式系统开发:感知、决策与控制实战
  • 面向金融文本的事件抽取与风险传导建模,当AI读懂金融“潜台词”:事件抽取与风险传导建模如何预判下一场风暴?
  • 不止于配置:用Eigen和Qt Quick 3D做个旋转立方体,实战理解线性代数
  • 什么是大模型:概念、分类与当前主流模型全梳理
  • 从录音到文字,2026年这5款免费录音转文字软件怎么选
  • 【linux学习】linux基本指令02
  • 如何通过LizzieYzy围棋AI分析工具在30天内实现棋力突破:从入门到实战的完整指南
  • 2026最新Xshell-8.0安装教程(官方免费正版,无需破解)
  • 基于Monaco Editor与AI大模型构建Web版智能代码编辑器的实践
  • 个人 AI 记忆系统:我的构想与三个落地方向
  • 跨平台B站视频下载:BilibiliDown完整使用指南
  • 仅限档案学研究者获取:NotebookLM定制提示词库V2.3(含17个NARA/中国第一历史档案馆认证模板)
  • 性价比高的AI应用厂家
  • 终极免费NCM转换指南:3分钟解锁你的网易云音乐
  • 终极指南:如何用免费开源软件FanControl完全掌控你的电脑风扇
  • 「PKUWC2018」Slay the Spire
  • LVGL字体优化实战:如何将中文字库放到外部SPI Flash并动态加载(节省内部RAM)
  • @Autowired 和 @Resource 的区别
  • 国产CPU与自研Wi-Fi 6芯片协同,构建自主可控高速无线连接方案
  • 贪心——划分字母区间
  • COLMAP重建翻车了?NeRF数据预处理中相机位姿估计的3个常见陷阱与调试技巧
  • AI专著生成工具评测:快速产出20万字专著,哪款最值得用?
  • 从Web空间到邮件服务器:Linux磁盘配额quota的3个真实生产环境应用案例详解
  • Source Han Serif CN:7款免费开源字体如何重塑你的中文排版体验
  • C语言条件编译:从语法到工程实践的高级应用指南