• 栈题目:解析布尔表达式


    题目

    标题和出处

    标题:解析布尔表达式

    出处:1106. 解析布尔表达式

    难度

    6 级

    题目描述

    要求

    给你一个以字符串形式表述的布尔表达式 expression \texttt{expression} expression,返回该式的运算结果。

    有效的表达式需遵循以下约定:

    • "t" \texttt{"t"} "t",运算结果为 True \texttt{True} True
    • "f" \texttt{"f"} "f",运算结果为 False \texttt{False} False
    • "!(expr)" \texttt{"!(expr)"} "!(expr)",运算过程为对内部表达式 expr \texttt{expr} expr 进行逻辑非的运算;
    • "&(expr1,expr2, … )" \texttt{"\&(expr1,expr2,\ldots)"} "&(expr1,expr2,)",运算过程为对 2 \texttt{2} 2 个或以上内部表达式 expr1,   expr2,   … \texttt{expr1, expr2, \ldots} expr1, expr2,  进行逻辑与的运算;
    • "|(expr1,expr2, … )" \texttt{"|(expr1,expr2,\ldots)"} "|(expr1,expr2,)",运算过程为对 2 \texttt{2} 2 个或以上内部表达式 expr1,   expr2,   … \texttt{expr1, expr2, \ldots} expr1, expr2,  进行逻辑或的运算。

    示例

    示例 1:

    输入: expression   =   "!(f)" \texttt{expression = "!(f)"} expression = "!(f)"
    输出: true \texttt{true} true

    示例 2:

    输入: expression   =   "|(f,t)" \texttt{expression = "|(f,t)"} expression = "|(f,t)"
    输出: true \texttt{true} true

    示例 3:

    输入: expression   =   "&(t,f)" \texttt{expression = "\&(t,f)"} expression = "&(t,f)"
    输出: false \texttt{false} false

    示例 4:

    输入: expression   =   "|(&(t,f,t),!(t))" \texttt{expression = "|(\&(t,f,t),!(t))"} expression = "|(&(t,f,t),!(t))"
    输出: false \texttt{false} false

    数据范围

    • 1 ≤ expression.length ≤ 20000 \texttt{1} \le \texttt{expression.length} \le \texttt{20000} 1expression.length20000
    • expression \texttt{expression} expression {‘(’,   ‘)’,   ‘&’,   ‘|’,   ‘!’,   ‘t’,   ‘f’,   ‘,’} \texttt{\{`(', `)', `\&', `|', `!', `t', `f', `,'\}} {‘(’, ‘)’, ‘&’, ‘|’, ‘!’, ‘t’, ‘f’, ‘,’} 中的字符组成
    • expression \texttt{expression} expression 是以上述形式给出的有效表达式,表示一个布尔值

    解法

    思路和算法

    布尔表达式中,每个逻辑运算符(与、或、非)都对后面的一对括号内的内部表达式进行运算。由于需要根据每一对匹配的括号进行解析和运算,寻找匹配的括号需要借助栈的数据结构,因此可以使用栈实现解析布尔表达式。

    由于布尔表达式中的逗号的作用是分隔内部表达式,并不影响布尔表达式的结果,因此可以跳过逗号,只对非括号字符解析和运算。

    从左到右遍历布尔表达式 expression \textit{expression} expression,遇到非括号且非右括号的字符则入栈,遇到右括号则开始解析,解析过程如下。

    1. 将栈内的元素依次出栈,直到遇到左括号,计算出栈的 ‘t’ \text{`t'} ‘t’ ‘f’ \text{`f'} ‘f’ 的个数。

    2. 将左括号出栈,然后将逻辑运算符出栈。

    3. 根据逻辑运算符计算当前内部表达式的值:

      • 如果逻辑运算符是 ‘&’ \text{`\&'} ‘&’,则是逻辑与运算,当 ‘f’ \text{`f'} ‘f’ 的个数等于 0 0 0 时,内部表达式的值为 ‘t’ \text{`t'} ‘t’,否则内部表达式的值为 ‘f’ \text{`f'} ‘f’

      • 如果逻辑运算符是 ‘|’ \text{`|'} ‘|’,则是逻辑或运算,当 ‘t’ \text{`t'} ‘t’ 的个数大于 0 0 0 时,内部表达式的值为 ‘t’ \text{`t'} ‘t’,否则内部表达式的值为 ‘f’ \text{`f'} ‘f’

      • 如果逻辑运算符是 ‘!’ \text{`!'} ‘!’,则是逻辑非运算,当 ‘f’ \text{`f'} ‘f’ 的个数大于 0 0 0 时,内部表达式的值为 ‘t’ \text{`t'} ‘t’,否则内部表达式的值为 ‘f’ \text{`f'} ‘f’

    4. 将内部表达式的值入栈。

    重复上述操作,直到遍历完毕布尔表达式。

    由于 expression \textit{expression} expression 是有效的布尔表达式,因此一定能正确解析,遍历结束时,栈内只有一个元素,为布尔表达式的结果。如果栈内的元素是 ‘t’ \text{`t'} ‘t’,返回 true \text{true} true,否则返回 false \text{false} false

    代码

    class Solution {
        public boolean parseBoolExpr(String expression) {
            Deque<Character> stack = new ArrayDeque<Character>();
            int length = expression.length();
            for (int i = 0; i < length; i++) {
                char c = expression.charAt(i);
                if (c == ',') {
                    continue;
                } else if (c == ')') {
                    int tCount = 0, fCount = 0;
                    while (stack.peek() != '(') {
                        char prev = stack.pop();
                        if (prev == 't') {
                            tCount++;
                        } else if (prev == 'f') {
                            fCount++;
                        }
                    }
                    stack.pop();
                    char op = stack.pop();
                    if (op == '&') {
                        char curr = fCount == 0 ? 't' : 'f';
                        stack.push(curr);
                    } else if (op == '|') {
                        char curr = tCount > 0 ? 't' : 'f';
                        stack.push(curr);
                    } else if (op == '!') {
                        char curr = fCount > 0 ? 't' : 'f';
                        stack.push(curr);
                    }
                } else {
                    stack.push(c);
                }
            }
            return stack.pop() == 't';
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    复杂度分析

    • 时间复杂度: O ( n ) O(n) O(n),其中 n n n 是布尔表达式 expression \textit{expression} expression 的长度。需要遍历布尔表达式一次,每个字符最多入栈和出栈各一次。

    • 空间复杂度: O ( n ) O(n) O(n),其中 n n n 是布尔表达式 expression \textit{expression} expression 的长度。空间复杂度主要取决于栈空间,栈内元素个数不会超过 n n n

  • 相关阅读:
    瀑布流使用虚拟列表性能优化
    DRF02-请求响应与路由
    面试题:MySQL事务的ACID如何实现?
    外包干了3天,技术退步明显.......
    MySQL 权限变更,何时生效?
    C++并发与多线程(2) | 线程运行开始和结束的基本方式
    uniapp刻度尺的实现(swiper)滑动打分器
    如何修改Notes邮箱中的收件箱标题宽度
    在 SQL Server 中,可以使用加号运算符(+)来拼接字符串。但是,如果需要拼接多个字符串或表中的字段,就需要使用内置的拼接函数了
    go get 拉取报错The project you were looking for could not be found的解决方法
  • 原文地址:https://blog.csdn.net/stormsunshine/article/details/120890035