LeetCode每日一题系列
题目:1106. 解析布尔表达式
难度:困难
题目
给你一个以字符串形式表述的 布尔表达式(boolean) expression,返回该式的运算结果。
有效的表达式需遵循以下约定:
- “t”,运算结果为 True
- “f”,运算结果为 False
- “!(expr)”,运算过程为对内部表达式 expr 进行逻辑 非的运算(NOT)
- “&(expr1,expr2,…)”,运算过程为对 2 个或以上内部表达式 expr1, expr2, … 进行逻辑
与的运算(AND) - “|(expr1,expr2,…)”,运算过程为对 2 个或以上内部表达式 expr1, expr2, … 进行逻辑
或的运算(OR)
示例
示例 1:
输入:expression = “!(f)”
输出:true
示例 2:
输入:expression = “|(f,t)”
输出:true
示例 3:
输入:expression = “&(t,f)”
输出:false
示例 4:
输入:expression = “|(&(t,f,t),!(t))”
输出:false
提示:
1 <= expression.length <= 20000
expression[i] 由 {‘(’, ‘)’, ‘&’, ‘|’, ‘!’, ‘t’, ‘f’, ‘,’} 中的字符组成。
expression 是以上述形式给出的有效表达式,表示一个布尔值。
思路
-
遇到带有括号的题第一时间应该就想到栈
-
这里使用栈signals记录所有运算符号,用栈number记录所有的操作数
-
遍历一遍给定的expression,可能会遇到以下情况
- 遇到’!‘或’&‘或’|',这几个就是运算符号,我们直接依次压入栈signals中
- 遇到’t’或’f’,这俩是操作数,我们可以依次压入number中
- 遇到’(',左括号作为分割与前一个括号的分隔符,我们可以向栈number中压入空字符串来辨识
- 遇到’)',遇到右括号证明我们要向前方直至上一个分隔符进行运算了,这时候对应signals的栈顶元素也就是我们所需要的运算符号,我们弹出signals的栈顶元素记作signal。然后依次弹出number中的元素(直到遇到空字符串停止)做signal运算,最后删除分隔符,将运算结果再压入栈中供后面使用即可
-
直到遍历完给定expression中的元素,number栈中必定只剩下最后一个结果元素,返回即可
题解
class Solution:
def parseBoolExpr(self, expression: str) -> bool:
# 定义运算符号和操作数栈
signals = []
number = []
# 遍历
for i in expression:
# 遇到运算符
if i in '!|&':
signals.append(i)
# 遇到操作数
elif i == 't' or i == 'f':
# 注意压入的是True和False
number.append(True if i == 't' else False)
# 遇到右括号
elif i == ')':
# 弹出运算符
signal = signals.pop()
# 下面分情况进行运算
tmp = number.pop()
# !直接取反即可,但是要先删除空字符串
if signal == '!':
number.pop()
number.append(not tmp)
elif signal == '&':
# 弹到分隔符为止,下同理
while number[-1] !='':
tmp_ = number.pop()
tmp = tmp and tmp_
number.pop()
number.append(tmp)
else:
while number[-1] != '':
tmp_ = number.pop()
tmp = tmp or tmp_
number.pop()
number.append(tmp)
# 遇到左括号
elif i == '(':
number.append('')
# 返回number首元素即可
return number[0]