【算法】Longest Valid Parentheses 最长有效括号

本文深入解析了求解最长有效括号子串的问题,通过分析括号特性,提出了一种从左到右遍历并计算有效括号长度的算法。以实际例子演示算法过程,最终实现了代码解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【算法】Longest Valid Parentheses 最长有效括号

题目

Given a string containing just the characters ‘(’ and ‘)’, find the length of the longest valid (well-formed) parentheses substring.

Example 1:

Input: "(()"
Output: 2
Explanation: The longest valid parentheses substring is "()"

Example 2:

Input: ")()())"
Output: 4
Explanation: The longest valid parentheses substring is "()()"

给出一个只含有 “(”、")" 的字符串,寻找字符串中最长的有效括号的长度。

解题思路

这里就需要分析一下 “()” 的特性了:

  1. “()” 的长度为 2
  2. ”()“ 左右位置若存在有效括号,则可以进行拼接
  3. “()” 若有效,且其中间位置存在字符,则中间的字符串也一定为有效括号

依据这三点特性,可以考虑如下思路来寻找最长括号:

  1. 从左到右遍历字符串,找到有效的括号,并计算其本身的长度
    • 以找到 “)” 为 当前标识 ,再寻找与其匹配的 “(”,若找到则为有效括号
    • 假设当前有效括号中间含有有效括号M,寻找与其匹配的 “(”
      • 找到当前字符 “)” 的位置为 i ,每个有效括号的当前最长长度存进 max[i],
      • 当前位置 i 左移到 有效括号M 的左侧( 左移 max[i-1] + 1 位),即为当前有效括号的 “(” 的位置 j = i - 1 - max[i-1]
      • 当且仅当位置 j 的字符存在且为 “(” 时,当前有效括号的假设才成功,当前有效括号的长度为当前左右括号长度 2 加上 有效括号M 的长度 max[i-1],( 2 + max[i-1])
  2. 由于是从左到右遍历,所以若左边位置为有效括号(有效括号L),计算最长长度时,需要加上 有效括号L 的长度 max[j-1]
  3. 计算完 max[i] 与结果容器 res 做较大值比较,赋较大值给 res
  4. 遍历结束,返回 res 即为最长有效括号的长度

PS: 有效括号M 若存在,其长度为 max[i-1] 有值, 有效括号M 若不存在 max[i-1] 为 0,若 当前有效括号 中间位置没有字符时,i-1 位置为 “(”,其在max的值max[i-1]也为 0 ,所以 当前有效括号 中间没有字符时的长度计算方式和 有效括号M 不存在时的计算方式是一致的,用 j = i - 1 - max[i-1] 寻找匹配 “(” 的方式可以同时解决。

代码实现

Runtime: 12 ms
Memory: 20.9 MB

func longestValidParentheses(_ s: String) -> Int {
        let len = s.count
        // 长度小于 2 的时候,成不了一组 () 所以返回 0
        if len < 2 {
            return 0
        }
        // 将 s 转换成数组,方便操作
        let s = Array(s)
        // max 数组 记录当前有效括号最大长度
        var max = Array(repeating: 0, count: len)
        // res 作为结果
        var res = 0
        // 从 1 开始遍历 s
        for i in 1 ..< len {
            // 只有当前字符为 ")" 时,才有可能出现有效括号
            if s[i] == ")" {
                // 用 i 减去 max[i-1] 的中间位置有效括号长度,再减去当前字符长度 1,即为与当前有效括号的 ( 的位置 j
                let j = i - 1 - max[i-1];
                // 只有当 j >= 0,并且 s[j] 为 ( 时,有效括号才匹配
                if j >= 0 && s[j] == "(" {
                    //有效括号匹配,更新 max[i] 的值,当前成对括号长度 2 ,中间位置有效括号长度 max[i-1],左侧有效括号长度 max[j-1],加和在一起
                    max[i] = 2 + max[i-1] + (j > 1 ? max[j-1] : 0)
                    //更新较大值到 res
                    res = max[i] > res ? max[i] : res
                }
            }
        }
        return res
    }

代码地址:https://github.com/sinianshou/EGSwiftLearning

### 回答1: 使用动态规划解决最长括号匹配问题的代码如下:int lengthOfLongestValidParentheses(string s) { int n = s.length(), maxLen = 0; vector<int> dp(n, 0); for (int i = 1; i < n; i++) { if (s[i] == ')') { if (s[i - 1] == '(') { dp[i] = (i - 2 >= 0 ? dp[i - 2] : 0) + 2; } else if (i - dp[i - 1] - 1 >= 0 && s[i - dp[i - 1] - 1] == '(') { dp[i] = dp[i - 1] + 2 + ((i - dp[i - 1] - 2 >= 0) ? dp[i - dp[i - 1] - 2] : 0); } maxLen = max(maxLen, dp[i]); } } return maxLen; } ### 回答2: 以下是用动态规划算法最长括号匹配问题的代码: ```python def longest_valid_parentheses(s: str) -> int: n = len(s) if n == 0: return 0 dp = [0] * n ans = 0 for i in range(1, n): if s[i] == ')': if s[i - 1] == '(': if i >= 2: dp[i] = dp[i - 2] + 2 else: dp[i] = 2 elif i - dp[i - 1] > 0 and s[i - dp[i - 1] - 1] == '(': if i - dp[i - 1] >= 2: dp[i] = dp[i - 1] + dp[i - dp[i - 1] - 2] + 2 else: dp[i] = dp[i - 1] + 2 ans = max(ans, dp[i]) return ans ``` 该算法使用动态规划来求解最长括号匹配问题。定义一个长度为n的dp数组,其中dp[i]表示以下标为i的字符结尾的最长有效括号子串的长度。遍历字符串s,当遇到'('时,不需要做任何计算;当遇到')'时,分为两种情况:如果前一个字符是'(',则dp[i] = dp[i-2] + 2;如果前一个字符是')',则需要判断前一个字符所对应的最长有效括号子串的前一个字符是否是'(',如果是,则dp[i] = dp[i-1] + dp[i-dp[i-1]-2] + 2。最后,取dp数组中的最大值即为最终的结果。算法的时间复杂度为O(n),空间复杂度为O(n)。 ### 回答3: 最长括号匹配问题可以使用动态规划算法来解决,具体代码如下: ```python def longestValidParentheses(s): n = len(s) if n < 2: return 0 dp = [0] * n # dp[i]表示以s[i]为结尾的最长括号长度 max_length = 0 for i in range(1, n): if s[i] == ')': if s[i-1] == '(': # 形如 "()" 的匹配 dp[i] = dp[i-2] + 2 if i >= 2 else 2 elif i - dp[i-1] > 0 and s[i - dp[i-1] - 1] == '(': # 形如 "))" dp[i] = dp[i-1] + dp[i - dp[i-1] - 2] + 2 if i - dp[i-1] >= 2 else dp[i-1] + 2 max_length = max(max_length, dp[i]) return max_length ``` 原理解释: 动态规划的思路是从左到右遍历字符串,维护一个dp数组来记录以当前字符为结尾的最长括号长度。 在遍历过程中,我们需要处理两种情况: 1. 形如 "()" 的匹配:如果当前字符是")",且前一个字符是"(",则可以形成一个有效的括号匹配,这时dp[i]的值可以由dp[i-2] + 2得到,也即前一个最长括号长度再加上当前匹配的长度2。 2. 形如 "))" - 如果当前字符是")",且前一个字符也是")",我们需要判断前一个最长括号匹配的前一个字符是否是"(",如果是,则可以形成一个有效的括号匹配,并且dp[i]的值可以由前一次最长括号长度dp[i-1]再加上到前一个有效括号匹配的前一个位置的最长括号长度dp[i - dp[i-1] - 2],再加上当前匹配的长度2得到。此时需要特别注意边界情况,即当i - dp[i-1] < 2时,没有前一个有效的括号匹配,所以直接加上当前匹配的长度2即可。 遍历结束后,返回dp数组的最大值,即为最长括号匹配的长度。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值