问题描述
小R有一个括号字符串 s,他想知道这个字符串是否有效。如果不是有效字符串,最少需要插入多少个括号才能使其有效?
有效括号字符串定义
- 空字符串是有效的。
- 如果
A和B是有效的,那么AB也是有效的。 - 如果
A是有效的,那么(A)也是有效的。
输入输出要求
- 输入:一个括号字符串
s。 - 输出:最少需要插入多少个括号,使得
s成为有效的括号字符串。
示例分析
| 输入 | 输出 | 解释 |
|---|---|---|
()) | 1 | 插入一个左括号,变为 (())。 |
((( | 3 | 插入三个右括号,变为 ((()))。 |
() | 0 | 已经是有效字符串,不需要插入。 |
()))(( | 4 | 插入两个左括号和两个右括号,变为 ((()))(())。 |
问题分析
直观解法思路
遍历字符串时,我们需要:
- 追踪当前未匹配的左括号数量。
- 记录需要插入的左括号数量。
遍历规则
-
遇到左括号
(:增加未匹配的左括号计数。 -
遇到右括号
):- 如果有未匹配的左括号,抵消一个左括号。
- 否则,增加需要插入的左括号计数。
最终结果为:需要插入的左括号 + 未匹配的左括号。
代码实现
def solution(s: str) -> int:
left_unmatched = 0
insert_count = 0
for char in s:
if char == '(':
# 遇到左括号,增加未匹配计数
left_unmatched += 1
elif char == ')':
# 遇到右括号,尝试抵消一个左括号
if left_unmatched > 0:
left_unmatched -= 1
else:
# 如果没有未匹配的左括号,需插入一个左括号
insert_count += 1
# 最后,未匹配的左括号也需要插入对应的右括号
return insert_count + left_unmatched
if __name__ == '__main__':
print(solution("())") == 1)
print(solution("(((") == 3)
print(solution("()))((") == 4)
print(solution("(((()))())))((") == 4)
代码解析
核心变量
left_unmatched:用于追踪未匹配的左括号(。insert_count:记录需要插入的括号数量。
关键逻辑
-
遍历字符串:
- 遇到
(,直接累加未匹配计数。 - 遇到
),如果有未匹配的左括号,则抵消;否则,记录一次插入左括号的需求。
- 遇到
-
处理结束时的未匹配左括号:
- 剩余的左括号每个需要一个右括号才能匹配。
时间复杂度
- 时间复杂度:O(n),只需线性遍历字符串一次。
- 空间复杂度:O(1),仅使用常数额外空间。
解题技巧与扩展
技巧总结
-
括号匹配问题的通用解法:
- 使用栈是处理括号匹配问题的经典方法,但对于本题,栈的额外空间可以通过计数器优化掉。
-
边界条件的处理:
- 空字符串的处理需要考虑。
- 单侧括号的连续性(如
(((或))))是测试重点。
总结
括号匹配问题在算法中广泛应用,尤其是在解析器、代码编辑器等工具中。本篇文章通过线性扫描与简单计数的思路解决了这个经典的算法题目。