0%

最长有效括号 -- LeetCode[32]

【Hard】给定一个只包含 ‘(‘ 和 ‘)’ 的字符串,找出最长的包含有效括号的子串的长度。

假设字符串为S

动态规划

一开始我连动态规划的“通项式”都想的稀里糊涂的…

动态规划的要点在于写出第i项的通项公式。在这个题中,dp[i]的值表示以第i个字符为结束字符的最长有效子串的长度。那么S[i]必然要求得是 ) ,以 ( 结尾的 dp 值应该都是0。所以只需要计算 ) 的dp值,取最大的即可。

根据经验,想象一下,一般来说的有效括号是 e() 或者 (e)。其中e是已知的有效子串,即dp[i-1]。

  1. 如果S[i] == ) && S[i-1] == (:
    dp[i] = dp[i-2] + 2

  2. 如果S[i] == ) && S[i-1] == ) && S[i-dp[i-1]-1] == (
    dp[i] = dp[i-1] + dp[i-dp[i-1]-2] + 2

重点在于:还要加一个dp[i-dp[i-1]-2],你细品…

算法复杂度没什么好说
时间复杂度:O(n)
空间复杂度:O(n)

当我以为动态规划法应该是效率最高的,结果看了一下discuss,还是“山外有山,人外有人”啊。

栈确实是括号的匹配的常用算法。不过之前只见过用于判断字符串是否合法。一般可以通过A用法…衍生一下…变为B用法

遍历字符串

  1. 如果是 ( ,那么把当前的索引入栈。
  2. 如果是 ),那么把栈顶的出栈,与当前的索引值求差值,这个差值,便可用于更新最大值。如果栈底空了,就放弃当前这个字符。

不过这里再细品一下,似乎栈的使用与动态规划如出一辙,只不过动态规划中的dp[<i]存储的是每一个i下的结果值,而本题目只需要一个最大值。栈存储的是索引,所以也可以求出最大值。

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

计数器法

我一直在思考这个方法应该怎么去理解它…

括号匹配的子串其实只需要满足以下 两 个条件就可以:

  1. () 的数量一致
  2. 第一个必须得是 (, 最后一个必须得是)

第一个条件,可以通过计数来搞定。第二个可以通过正反两次遍历来搞定。

正向遍历的时候,如果)的数量 >(的数量了(其实也就是出现了 e) 的情况,e是有效子串),那么就重置数量计算。

反向遍历的时候,如果(的数量 >)的数量了(其实也就是出现了 (e 的情况,e是有效子串),那么就重置数量计算。

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