最长连续有效括号子串的变种——允许最多k次失配的最长连续有效括号子串
字数 878 2025-11-05 23:45:42

最长连续有效括号子串的变种——允许最多k次失配的最长连续有效括号子串

题目描述:
给定一个只包含'('和')'的字符串s和一个非负整数k,要求找到最长的连续子串,使得这个子串在最多修改k个字符(可以将'('改为')'或将')'改为'(')后能够变成有效的括号序列。

解题过程:

  1. 问题分析:
  • 有效括号序列需要满足:左右括号数量相等,且任意前缀中左括号数量不少于右括号数量
  • 允许最多k次修改意味着我们可以容忍一定的不匹配
  • 需要找到最长的连续子串
  1. 动态规划状态定义:
    定义dp[i][j][l]表示考虑前i个字符,当前平衡度为j(左括号比右括号多的数量),已经使用了l次修改的情况下,能够达到的最长有效子串长度。

但三维DP复杂度较高,我们可以采用更优化的双指针方法。

  1. 滑动窗口解法:
    我们可以从左到右和从右到左分别扫描两次来处理:

第一次扫描(从左到右):

  • 用left和right计数器记录左右括号数量
  • 当right > left + k时,说明不匹配过多,需要移动左指针
  • 记录当前窗口长度

具体步骤:

  1. 初始化left = 0, right = 0, start = 0, maxLen = 0

  2. 遍历字符串:

    • 如果是'(',left++

    • 如果是')',right++

    • 如果right > left + k:

      • 需要移动左指针直到平衡
      • 移动左指针,调整left或right计数
    • 如果left >= right:

      • 更新最大长度maxLen = max(maxLen, 2 * min(left, right))
  3. 第二次扫描(从右到左)处理相反情况

  4. 算法实现细节:

def longestValidParentheses(s: str, k: int) -> int:
    def scan(s, k, reverse=False):
        left = right = 0
        max_len = 0
        l = 0
        
        for r in range(len(s)):
            if (not reverse and s[r] == '(') or (reverse and s[r] == ')'):
                left += 1
            else:
                right += 1
            
            # 当不匹配超过k次时,移动左指针
            while right > left + k:
                if (not reverse and s[l] == '(') or (reverse and s[l] == ')'):
                    left -= 1
                else:
                    right -= 1
                l += 1
            
            # 更新最大长度
            if left >= right:
                max_len = max(max_len, 2 * min(left, right))
        
        return max_len
    
    return max(scan(s, k), scan(s, k, reverse=True))
  1. 复杂度分析:
  • 时间复杂度:O(n),每个字符最多被访问两次
  • 空间复杂度:O(1),只使用了常数级别的额外空间
  1. 示例验证:
    输入:s = "()())", k = 1
    过程:
  • 从左到右扫描:可以修改最后一个')'为'(',得到"()()(",但最优是修改中间的')'得到"()()"
  • 最终找到长度为4的有效子串

这种解法通过双向扫描确保了各种情况都被考虑到,同时利用滑动窗口优化了时间复杂度。

最长连续有效括号子串的变种——允许最多k次失配的最长连续有效括号子串 题目描述: 给定一个只包含'('和')'的字符串s和一个非负整数k,要求找到最长的连续子串,使得这个子串在最多修改k个字符(可以将'('改为')'或将')'改为'(')后能够变成有效的括号序列。 解题过程: 问题分析: 有效括号序列需要满足:左右括号数量相等,且任意前缀中左括号数量不少于右括号数量 允许最多k次修改意味着我们可以容忍一定的不匹配 需要找到最长的连续子串 动态规划状态定义: 定义dp[ i][ j][ l ]表示考虑前i个字符,当前平衡度为j(左括号比右括号多的数量),已经使用了l次修改的情况下,能够达到的最长有效子串长度。 但三维DP复杂度较高,我们可以采用更优化的双指针方法。 滑动窗口解法: 我们可以从左到右和从右到左分别扫描两次来处理: 第一次扫描(从左到右): 用left和right计数器记录左右括号数量 当right > left + k时,说明不匹配过多,需要移动左指针 记录当前窗口长度 具体步骤: 初始化left = 0, right = 0, start = 0, maxLen = 0 遍历字符串: 如果是'(',left++ 如果是')',right++ 如果right > left + k: 需要移动左指针直到平衡 移动左指针,调整left或right计数 如果left >= right: 更新最大长度maxLen = max(maxLen, 2 * min(left, right)) 第二次扫描(从右到左)处理相反情况 算法实现细节: 复杂度分析: 时间复杂度:O(n),每个字符最多被访问两次 空间复杂度:O(1),只使用了常数级别的额外空间 示例验证: 输入:s = "()())", k = 1 过程: 从左到右扫描:可以修改最后一个')'为'(',得到"()()(",但最优是修改中间的')'得到"()()" 最终找到长度为4的有效子串 这种解法通过双向扫描确保了各种情况都被考虑到,同时利用滑动窗口优化了时间复杂度。