最长连续有效括号子串的变种——允许最多k次失配的最长连续有效括号子串
字数 878 2025-11-05 23:45:42
最长连续有效括号子串的变种——允许最多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))
-
-
第二次扫描(从右到左)处理相反情况
-
算法实现细节:
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))
- 复杂度分析:
- 时间复杂度:O(n),每个字符最多被访问两次
- 空间复杂度:O(1),只使用了常数级别的额外空间
- 示例验证:
输入:s = "()())", k = 1
过程:
- 从左到右扫描:可以修改最后一个')'为'(',得到"()()(",但最优是修改中间的')'得到"()()"
- 最终找到长度为4的有效子串
这种解法通过双向扫描确保了各种情况都被考虑到,同时利用滑动窗口优化了时间复杂度。