20. 有效的括号

97 阅读4分钟

【题目】

给定一个只包括 '('')''{''}''['']' 的字符串 s ,判断字符串是否有效。

有效字符串需满足:

  1. 左括号必须用相同类型的右括号闭合。
  2. 左括号必须以正确的顺序闭合。
  3. 每个右括号都有一个对应的相同类型的左括号。

示例 1:

输入: s = "()"
输出: true

示例 2:

输入: s = "()[]{}"
输出: true

示例 3:

输入: s = "(]"
输出: false

提示:

  • 1 <= s.length <= 104
  • s 仅由括号 '()[]{}' 组成

【题目解析】

这个问题可以通过一种称为的数据结构来解决。栈是一种后进先出(LIFO)的数据结构,它只允许在一端(通常称为"顶部")进行添加数据(推入)和移除数据(弹出)。算法的核心思想是扫描字符串,每当遇到开括号时,将其推入栈中。每当遇到闭括号时,检查栈顶的元素。如果栈顶元素是与之匹配的开括号,就将其弹出栈;如果不匹配或栈为空,则字符串无效。如果在完成扫描后栈为空,则字符串有效。

class Solution:
    def isValid(self, s: str) -> bool:
        # 初始化一个栈
        stack = []
        # 创建一个映射,用于查找匹配的括号
        bracket_map = {')': '(', '}': '{', ']': '['}

        # 遍历字符串中的每个字符
        for char in s:
            # 如果是闭括号
            if char in bracket_map:
                # 弹出栈顶元素,若栈为空,则赋予一个虚拟的字符
                top_element = stack.pop() if stack else '#'
                # 如果栈顶元素与当前闭括号不匹配,则字符串无效
                if bracket_map[char] != top_element:
                    return False
            else:
                # 如果是开括号,推入栈中
                stack.append(char)

        # 如果栈为空,则所有括号都有效匹配
        return not stack

image.png

【总结】

适用问题类型: 有效的括号问题属于匹配类问题,其特点是需要检查一系列元素中是否存在合法的配对关系。这类问题广泛存在于编程语言的语法分析、文本编辑器的代码检查、以及日常开发中处理各类括号、标签和特殊字符的场景。此类问题的共同点是,对于每一个"开启"元素,都需要找到一个对应的"关闭"元素,并且它们的顺序必须正确。这不仅适用于简单的括号,也适用于比如 HTML 或 XML 标记的嵌套结构检查。

使用的算法: 本题的解法使用了这一数据结构的特性来解决问题。算法的核心是维护一个栈来跟踪未匹配的"开启"括号,当遇到一个"关闭"括号时,尝试从栈中弹出一个元素并检查它是否与之匹配。如果匹配,则继续处理字符串的下一个字符;如果不匹配或栈为空,则判定字符串为无效。有效的括号字符串意味着所有的"开启"括号在字符串中都找到了正确顺序的"关闭"括号。

算法细节

  1. 创建一个映射,用于快速查找每个"关闭"括号对应的"开启"括号。

  2. 遍历字符串,使用栈跟踪所有"开启"括号。

  3. 遇到"开启"括号时,将其推入栈中。

  4. 遇到"关闭"括号时,检查栈顶元素是否匹配:

    • 如果栈不为空且顶部元素匹配,弹出栈顶元素。
    • 如果栈为空或顶部元素不匹配,返回 false。
  5. 完成遍历后,如果栈为空,则所有括号都匹配;否则,括号不匹配。

总结: 本题展示了栈在处理成对匹配问题中的应用,栈的后进先出(LIFO)特性使它成为处理此类问题的理想选择。该问题的解决方案展现了栈的简洁性和高效性,它在算法设计中的应用是多样的,包括但不限于括号匹配,还有函数调用栈、回溯算法、深度优先搜索等算法和数据结构的核心组成部分。掌握了栈的使用和相关算法,我们就能够有效地解决一类包含顺序和配对逻辑的问题。

题目链接

有效的括号