一道典型的栈问题 - LeetCode 20

1,085 阅读2分钟

原题:leetcode.com/problems/va…

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

  • 左括号必须与相同类型的右括号闭合。
  • 左括号必须以正确的顺序闭合。
  • 空字符串被认为是有效字符串。

思路

一个有效的字符串括号必定会成对出现,因此对于一个有效的字符串而言,任意一个左括号必定可以在其后的某个位置找到和它配对的右括号,这个规则对所有整个字符串都有效。

因此如果假定一个字符串是有效的,对于非空字符串一定存在至少一对相邻配对的左右括号,比如 "({[]})","()[]{}" 这两个有效字符串均存在至少一对相邻的配对括号。假如我们拿掉相邻配对的括号,那么剩余的字符串也会出现至少一对相邻的配对括号。

接下来我们的目标就可以调整到找到这一对相邻的括号,然后一次配对,如同消消乐一般,直到整个字符串中配对的括号全部被拿掉,如果此时剩余的是一个空字符串,那么这就是一个有效的字符串。毫无疑问是最方便进行“消消乐”操作的数据结构。

栈 (stack)

堆栈(英语:stack)又称为堆叠,是计算机科学中的一种抽象数据类型,只允许在有序的线性数据集合的一端(称为堆栈顶端,英语:top)进行加入数据(英语:push)和移除数据(英语:pop)的运算。因而按照后进先出(LIFO, Last In First Out)的原理运作。
堆栈使用两种基本操作:推入(压栈,push)和弹出(弹栈,pop):

  • 推入:将数据放入堆栈顶端,堆栈顶端移到新放入的数据。
  • 弹出:将堆栈顶端数据移除,堆栈顶端移到移除后的下一笔数据。

接下来我们要做的,就是遍历整个字符串,不断的将前面的字符串压入栈底,如果找到要传入的字符和栈顶的字符配对,则将两个字符消除。我们可以得到如下判断逻辑:

  • 右括号如果不能在栈顶找到配对的左括号,则整个字符串是无效字符串;

代码

class Solution:
    def isValid(self, s: str) -> bool:
        stack = []

        pair = {
          ')': '(',
          ']': '[',
          '}': '{'
        }

        for char in s:
          # 栈为空时右括号先入必然不配对
          if len(stack) == 0:
            if pair.get(char) is not None:
              return False

          # 栈不为空时右括号进入
          if pair.get(char) is not None:
            if stack[0] == pair[char]:
              stack.pop(0)
            else:
              return False
          else:
            # 左括号不做判断, 直接入栈
            stack.insert(0, char)


        # 遍历完毕后栈为空说明有效
        return len(stack) == 0