最长有效括号。给定一个只包含 '(' 和 ')' 的字符串,找出最长的包含有效括号的子串的长度。
示例 1:
1 | |
示例 2:
1 | |
思路一
动态规划。令 dp[i] 表示截止到第 i 个字符为止的最长有效括号的长度,很显然,只有当子串以 ')' 结尾时,才有可能构成有效的子串,因此,我们只在遇到 ')' 的时候更新 dp。
- 当
s[i] = ')'并且s[i - 1] = '('时,即出现"......()"的子串,dp[i] = dp[i - 2] + 2 - 当
s[i] = ')'并且s[i - 1] = ')'时,即出现"......))"的子串,此时如果s[i - dp[i - 1] - 1] = '(',则dp[i] = dp[i - 1] + 2 + dp[i - dp[i-1] - 2]
时间复杂度 $O(n)$,空间复杂度 $O(n)$。
1 | |
思路二
使用堆栈,记录目前为止遇到的字符的下标,为了获取最大长度,首先将 -1 入栈。当遇到一个 ( 时,即将其下标入栈,遇到一个 ) 时,栈顶元素出栈,此时得到的有效括号的长度为当前 ) 的下标减去栈顶元素的差,如果栈为空,则将当前 ) 的下标入栈。
时间复杂度 $O(n)$,空间复杂度 $O(n)$。
1 | |
思路三
使用两个指示符 left 和 right,指示遇到的括号的数目。首先从左往右遍历,如果遇到 (,则 left + 1,如果遇到 ),则 right + 1,当 left 与 right 相等时,则此时可以计算当前有效括号的长度,即为 2 * right,如果 left > right,则令 left = right = 0。
然后,再从右往左遍历,操作与之前类似。
为什么还要从右往左遍历一遍呢,比如出现这样的字符串 ()((()),只从左往右遍历会忽略掉最大的有小括号。时间复杂度 $O(n)$,空间复杂度 $O(1)$。
1 | |