leetcode32. 最长有效括号

给定一个只包含 '('')' 的字符串,找出最长的包含有效括号的子串的长度。

示例 1:

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

示例 2:

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


方法一:动态规划

思路:

本题最暴力的方法就是枚举所有的子串,然后判断这个子串是否是有效的括号,维护最大长度的括号即可。这种想法的时间复杂度为O(N ^ 3),枚举为O(N ^ 2),判断还需要O(N),不能通过。

因为在上面遍历过程中,需要很多的重复计算,所以我们使用动态规划的方法来解决。

我们维护一个dp数组,dp[i]表示以s[i]为结尾的最长有效括号的长度。我们可以知道,s中的左括号的位置,对应的dp值为0。

下面我们找状态转移方程,我们遍历s,忽略'(',因为肯定为0,只考虑')':

  • 如果s[i-1] = '(',那么s[i-1]和s[i]构成了一个有效括号'()',再加上dp[i-2]即可,即dp[i] = dp[i-2] + 2。
  • 如果s[i-1] = ')',那么此时连续两个右括号,相当于这种情况'xxxx((。。。。。。))',此时遍历到最后的')',内层是满足条件的,长度为dp[i-1],需要看这个dp[i-1]所对应的有效括号的前面一个字符,是不是'(',如果是的话,这样就相当于在dp[i-1]外层加一层'()',dp[i-1] + 2。同时还需要考虑xxx是不是有效括号,如果是的话也要加上,长度为dp[i-dp[i-1]-2]。 所以dp[i] = dp[i-1] + 2 + dp[i-dp[i-1]-2]

考虑边界条件,只需要把dp[0]置为0即可,因为s的第一个元素对应的肯定是无效的。

我们在填写dp的时候,不断维护保存dp的最大值,返回即可。

  • 只遍历了一次,时间复杂度为O(N)。
  • 使用了一个dp数组,空间复杂度为O(N)。

代码:

class Solution:def longestValidParentheses(self, s: str) -> int:n = len(s)#初始化dpdp = [0 for _ in range(n)]res = 0#只有一个符号,返回0if n == 1:return 0#开始填写dp数组for i in range(1,n):#只考虑')',因为'('对应的肯定为0if s[i] == ')':#如果前一个是'(',即这两个符号时'()',长度+2if s[i-1] == '(':dp[i] = dp[i-2] + 2#res保存dp中的最大值res = max(res,dp[i])#如果前一个是')',则需考虑其他情况#相当于这种情况'xxxx((。。。。。。))',此时遍历到最后的')',#内层是满足条件的,dp[i-1],需要看这个dp[i-1]所对应的前面一个#是不是'(',这样就相当于在dp[i-1]外层加一层'()'。#同时还需要考虑xxx是不是合法括号,是的话也要加上#dp[i] = dp[i-1] + 2 + dp[i-dp[i-1]-2]else:#防止越界if i-dp[i-1]-1 >= 0 and s[i-dp[i-1]-1] == '(':#这里只需判断i-dp[i-1]-1 >= 0,而不需要管i-dp[i-1]-2#的原因是,如果i-dp[i-1]-1 == 0,那么后者为-1#根据python的特性,且此时是按顺序填写dp的,初始值是0#所以dp[-1]一定是0,不造成干扰,所以不需要再判断dp[i] = dp[i-1] + 2 + dp[i-dp[i-1]-2]res = max(res,dp[i])return res

结果:

方法二:遍历两次

思路:

这种方法我们考虑到leetcode22题括号生成的方法。

Andy Liu:leetcode22. 括号生成​zhuanlan.zhihu.com

有效的括号字符串,那么它的左右括号的数量相等,且从左到右遍历这个字符串的时候,左括号的数量一直大于等于右括号的数量。

所以我们遍历s,初始化两个变量left_num、right_num保存遍历到的左右括号数,

  • 当left_num = right_num时,此时一个有效括号长度为2 * left_num,更新res,继续遍历......
  • 当遇到left_num < right_num时,此时无效了,重新将left_num和right_num初始化为0,继续遍历。

上面的方法有一种情况无法处理,比如'((())'这种情况,因为left_num一直大于right_num,所以无法找到后面长度为4的答案。而如果从右向左遍历,则可以找到,所以我们再从右向左遍历一次,

从右向左遍历的时候,右括号的数量需要一直大于等于左括号数量。所以我们重新初始化两个变量,从右向左遍历,

  • 当left_num = right_num时,此时一个有效括号长度为2 * left_num,更新res,继续遍历......
  • 当遇到left_num > right_num时,此时无效了,重新将left_num和right_num初始化为0,继续遍历。

我们可以看到,从右向左遍历的时候,比如'(()))'这种情况无法处理,而从左向右遍历可以处理。因此两次遍历可以将这些情况都考虑在内。最后返回res即可。

  • 遍历两次,时间复杂度为O(2N),渐进时间复杂度为O(N)。
  • 只使用了几个变量,空间复杂度为O(1)。

代码:

class Solution:def longestValidParentheses(self, s: str) -> int:left_num = 0right_num = 0n = len(s)res = 0#从左到右遍历一次for i in range(n):if s[i] == '(':left_num += 1else:right_num += 1if left_num == right_num:res = max(res,2*left_num)elif left_num < right_num:left_num = right_num = 0left_num = 0right_num = 0#从右向左遍历一次for i in range(n-1,-1,-1):if s[i] == '(':left_num += 1else:right_num += 1if left_num == right_num:res = max(res,2*left_num)elif left_num > right_num:left_num = right_num = 0return res

结果:

无法使用带括号的初始值设定项初始化数组_leetcode32. 最长有效括号相关推荐

  1. 初始值设定项是啥c语言,无法指定数组的显式初始值设定项

    无法制止的痛(伤感语录)懂得爱就等于懂得泪这句话我深深的体会到了你是唯逐一个让我随时都可以掉下眼泪的人是不是爱一团体太深就会失掉自我在你面前我无法继续已抬不起头明知你不是故意的而我却总是感伤我怕我这样 ...

  2. 类型初始值设定项引发异常

    -上午打开VS编译程序的时候,突然出现了这个运行时错误"类型初始值设定项引发异常".昨天还没有这个错误呢,今天就突然出现,搞得我一头雾水.上网搜了一下,发现有很多人遇到了这个问题. ...

  3. Oracle.DataAccess.Client.OracleCommand”的类型初始值设定项引发异常

    Oracle.ManagedDataAccess.dll 连接Oracle数据库不需要安装客户端 最开始,连接Oracle 数据是需要安装客户端的,ado.net 后来由于微软未来不再支持 Syste ...

  4. <Module>的类型初始值设定项引发异常

    的类型初始值设定项引发异常 参考文章: (1)的类型初始值设定项引发异常 (2)https://www.cnblogs.com/RealWorld/p/7843440.html 备忘一下.

  5. “System.Transactions.Diagnostics.DiagnosticTrace”的类型初始值设定项引发异常。

    "System.Transactions.Diagnostics.DiagnosticTrace"的类型初始值设定项引发异常. 参考文章: (1)"System.Tran ...

  6. MathWorks.MATLAB.NET.Arrays.MWArray”的类型初始值设定项引发异常 解决方法

    MathWorks.MATLAB.NET.Arrays.MWArray"的类型初始值设定项引发异常 解决方法 参考文章: (1)MathWorks.MATLAB.NET.Arrays.MWA ...

  7. VMWARE错误-“VirtualInfrastructure.Utils.ClientsXml“的类型初始值设定项引发异常

    VMWARE错误-"VirtualInfrastructure.Utils.ClientsXml"的类型初始值设定项引发异常 参考文章: (1)VMWARE错误-"Vir ...

  8. Entityframework:“System.Data.Entity.Internal.AppConfig”的类型初始值设定项引发异常。

    Entityframework:"System.Data.Entity.Internal.AppConfig"的类型初始值设定项引发异常. 参考文章: (1)Entityframe ...

  9. C# 出现System.TypeInitializationException类型初始值设定项引发异常

    C# 出现System.TypeInitializationException类型初始值设定项引发异常 参考文章: (1)C# 出现System.TypeInitializationException ...

最新文章

  1. android上方导航条跳转页面,《成为大前端》系列 7. 多页面、页面跳转和Navigation模块...
  2. 从AK47到乌兹,这款控制器模块可以模拟不同物体体感
  3. 2021.02.02 Visual QA论文阅读
  4. OllyDBG完美教程(超强入门级)
  5. 2021双11上云狂欢节 | 爆款产品底价全面开售
  6. odoo10参考系列--视图一(列表视图)
  7. delphi接口带上请求头是什么意思_Python接口自动化之Token详解及应用
  8. c语言dfs算法,DFS算法源程序
  9. Javascript特效:获取选中内容分享至微博
  10. 拔叉零件的加工工艺、夹具以及拉刀设计
  11. 非常有用的微信公众号平台开发各种错误返回码一览表
  12. 衡量度量过程性能的几个指标
  13. 创业失败那天我在做什么
  14. Android中模拟点击软件的实现原理探究
  15. 项目成本管理名词解析
  16. java简单记事本代码_简单记事本的java程序代码
  17. Xshell用root用户连接Linux
  18. git统计提交代码量
  19. 五分钟用 linux搭建我的世界服务器
  20. 二手交易市场的数据流图

热门文章

  1. java 套接字 访问tcp_Java 网络编程(五) 使用TCP/IP的套接字(Socket)进行通信
  2. httpcliet发送body体_解决HTTP GET方法调用带有body问题
  3. pthread线程传递数据回主线程_操作系统4:线程(1)
  4. java 泛型参数写法_参数化类型——Java泛型
  5. android 使用pdf文件大小,Android 加载PDF文件的使用
  6. php获取微信图片访问权限,微信小程序访问图片出现403,图片防盗链的解决办法...
  7. sql的join语法解析
  8. 解决MYSQL不报错误详细信息的问题 Can‘t find error-message file
  9. redis-cli 链接redis命令
  10. csrf 攻击及防御