有效的括号

标签: 字符串

难度: Easy

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

有效字符串需满足:

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

示例 1:

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

示例 2:

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

示例 3:

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

提示:

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

Submission

运行时间: 36 ms

内存: 15 MB

class Solution:
    def isValid(self, s: str) -> bool:
        if len(s) % 2 == 1:
            return False

        half = len(s) // 2

        stack = []
        left = set('([{')
        for char in s:
            if char in left:
                stack.append(char)
                if len(stack) > half:
                    return False
            else:
                if len(stack) == 0:
                    return False
                if char == ')' and stack[-1] != '(':
                    return False
                if char == ']' and stack[-1] != '[':
                    return False
                if char == '}' and stack[-1] != '{':
                    return False
                stack.pop()

        return len(stack) == 0

Explain

这个题解使用了栈的数据结构来判断括号的有效性。具体思路如下: 1. 首先判断字符串长度是否为奇数,如果是奇数则一定不是有效的括号,直接返回 false。 2. 计算字符串长度的一半 half,作为左括号数量的上限。 3. 遍历字符串中的每个字符: - 如果当前字符是左括号,则将其压入栈中,并检查栈的大小是否超过 half,如果超过则说明左括号数量过多,直接返回 false。 - 如果当前字符是右括号,则检查栈是否为空,如果为空则说明没有与之匹配的左括号,直接返回 false。然后检查栈顶元素是否与当前右括号匹配,如果不匹配则直接返回 false,否则将栈顶元素弹出。 4. 遍历完成后,检查栈是否为空,如果为空则说明所有括号都正确匹配,返回 true,否则返回 false。

时间复杂度: O(n)

空间复杂度: O(n)

class Solution:
    def isValid(self, s: str) -> bool:
        # 如果字符串长度为奇数,一定不是有效的括号
        if len(s) % 2 == 1:
            return False
        
        # 计算字符串长度的一半,作为左括号数量的上限
        half = len(s) // 2
        
        stack = []
        left = set('([{')  # 用集合存储左括号,便于判断
        for char in s:
            if char in left:
                stack.append(char)  # 如果是左括号,压入栈中
                # 如果栈的大小超过一半,说明左括号数量过多
                if len(stack) > half:
                    return False
            else:
                # 如果栈为空,说明没有与之匹配的左括号
                if len(stack) == 0:
                    return False
                # 检查栈顶元素是否与当前右括号匹配
                if char == ')' and stack[-1] != '(':
                    return False
                if char == ']' and stack[-1] != '[':
                    return False
                if char == '}' and stack[-1] != '{':
                    return False
                stack.pop()  # 如果匹配,弹出栈顶元素
        
        # 如果栈为空,说明所有括号都正确匹配
        return len(stack) == 0

Explore

有效的括号序列必须是由成对的左右括号组成的。这意味着每一个左括号都必须有一个对应的右括号与之匹配,因此有效的括号字符串的总长度一定是偶数。如果括号字符串的长度是奇数,那么其中至少有一个括号无法找到匹配的对,因此可以直接判断为不是有效的括号序列。

如果一个有效的括号序列的总长度为n,那么其中必定包含n/2个左括号和n/2个右括号。在遍历输入字符串的过程中,如果任何时候压入栈中的左括号数量超过了n/2,这意味着剩余的字符中不可能有足够的右括号来匹配这些左括号,因为左括号已经超过了字符串应有的一半数量。因此,可以立即判断该字符串不是有效的括号序列。

在本题解中,目的是判断括号序列是否有效,因此只返回true或false是符合需求的。然而,在更复杂的应用场景中,如代码编辑器或调试工具中,提供详细的错误信息确实是非常有用的。在这种情况下,可以修改算法以记录错误发生的位置和类型,例如记录不匹配的括号和其位置,然后将这些详细信息返回给用户,以便更容易地识别和解决问题。

是的,栈中剩余的元素可以提供关于序列中未匹配括号的信息。例如,如果在算法完成后栈中仍然有元素,这些元素就是未找到匹配的右括号的左括号。通过分析这些左括号的类型和它们在栈中的位置,我们可以得到关于哪些括号未关闭的具体信息。在某些应用中,这些信息可以用来向用户提供具体的错误位置和建议,帮助用户快速定位和解决代码中的括号匹配错误。