【每日一题Day18】LC1106解析布尔表达式|栈

简介: &(expr1,expr2,...)",运算过程为对 2 个或以上内部表达式 expr1, expr2, ... 进行逻辑 与的运算(AND)

解析布尔表达式【LC1106】


A boolean expression is an expression that evaluates to either true or false. It can be in one of the following shapes:


  • 't' that evaluates to true.
  • 'f' that evaluates to false.
  • '!(subExpr)' that evaluates to the logical NOT of the inner expression subExpr.
  • '&(subExpr1, subExpr2, ..., subExprn)' that evaluates to the logical AND of the inner expressions subExpr1, subExpr2, ..., subExprn where n >= 1.
  • '|(subExpr1, subExpr2, ..., subExprn)' that evaluates to the logical OR of the inner expressions subExpr1, subExpr2, ..., subExprn where n >= 1.


Given a string expression that represents a boolean expression, return the evaluation of that expression.


It is guaranteed that the given expression is valid and follows the given rules.


给你一个以字符串形式表述的 布尔表达式(boolean) expression,返回该式的运算结果。


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


  • "t",运算结果为 True
  • "f",运算结果为 False
  • "!(expr)",运算过程为对内部表达式 expr 进行逻辑 非的运算(NOT)
  • "&(expr1,expr2,...)",运算过程为对 2 个或以上内部表达式 expr1, expr2, ... 进行逻辑 与的运算(AND)
  • "|(expr1,expr2,...)",运算过程为对 2 个或以上内部表达式 expr1, expr2, ... 进行逻辑 或的运算(OR)


比昨天的简单呐


两个栈


  • 思路:


。构建两个栈,分别存放运算符(!、&、|)以及布尔值和左括号((、t、f),然后模拟布尔运算


。遇到右括号时,将运算符弹出,并将左括号内的布尔值弹出,进行相应的运算,最后将该次结果保存在栈内


。最终结果即为栈顶元素


  • 实现


。注意:与和或操作为多元运算符,需要记录上次的结果,


初始变量时:或运算初始值为假不影响最终结果,与运算初始值为真不影响最终结果


class Solution {
    public boolean parseBoolExpr(String expression) {
        Deque<Character> stTf = new LinkedList<>();
        Deque<Character> stOpera = new LinkedList<>();
        for (int i = 0; i < expression.length(); i++){
            char c = expression.charAt(i);
            if (c == ','){
                continue;
            }else if (c == '(' || c == 't' || c == 'f'){
                stTf.addFirst(c);
            }else if (c == '!' || c == '&' || c == '|' ){
                stOpera.addFirst(c);
            }else if (c == ')'){ // 进行运算
                char opera = stOpera.pollFirst();
                // 或运算初始值为假不影响结果 与运算初始值为真不影响结果
                boolean tmp = opera == '|' ? false : true;
                while (stTf.peekFirst() != '('){
                    boolean flag = stTf.pollFirst() == 't' ? true : false;
                    if (opera == '|'){
                        tmp =  tmp || flag;
                    }else if ( opera == '!'){
                        tmp =  !flag;
                    }else { 
                        tmp = tmp && flag;
                    }
                }
                stTf.pollFirst();
                stTf.addFirst(tmp ? 't' : 'f');
            }
        }
        return stTf.pollFirst() == 't' ? true : false;
    }
}


  • 复杂度


。时间复杂度:O(n)


。空间复杂度:O(n)


一个栈


  • 思路:


。单个运算表达式的结果取决于运算符以及括号内t和f的个数,因此可以使用一个栈解决该问题


  • 如果运算符是 ‘!’,当f的个数为1时表达式的值为‘t’
  • 如果运算符是 ‘&’,当f的个数为0时表达式的值为‘t’
  • 如果运算符是 ‘|’,当t的个数大于0时表达式的值为‘t’


  • 实现


1.构建一个栈,存放运算符(!、&、|)以及布尔值和左括号((、t、f),然后模拟布尔运算

2.字符串遇到右括号时,将栈内左括号内的‘t’和‘f’弹出,并统计其个数

3.栈内遇到左括号时,将其弹出,并记录其下一个元素【运算符】

4.根据规律计算结果,并将其压入栈中

5.最终结果即为栈顶元素


  • 代码


class Solution {
    public boolean parseBoolExpr(String expression) {
        Deque<Character> st = new LinkedList<>();
        for (int i = 0; i < expression.length(); i++){
            char c = expression.charAt(i);
            if (c == ','){
                continue;
            }else if (c != ')' ){
                st.addFirst(c);
            }else { 
                // 统计t和f的个数
                int t = 0, f = 0;
                while (st.peekFirst() != '('){
                    if (st.pollFirst() == 't'){
                        t++;
                    }else{
                        f++;
                    }
                }
                st.pollFirst();
                char opera = st.pollFirst();
                // 根据运算符进行运算
                if (opera == '!'){
                    if (f == 1){
                        st.addFirst('t');
                    }else{
                        st.addFirst('f');
                    }
                }else if (opera == '&'){
                    if (f == 0){
                        st.addFirst('t');
                    }else{
                        st.addFirst('f');
                    }
                }else{
                    if (t > 0){
                        st.addFirst('t');
                    }else{
                        st.addFirst('f');
                    }
                }
            }
        }
        return st.pollFirst() == 't' ? true : false;
    }
}


  • 复杂度


。时间复杂度:O(n)

。空间复杂度:O(n)

目录
相关文章
|
11月前
|
存储 算法
非递归实现后序遍历时,如何避免栈溢出?
后序遍历的递归实现和非递归实现各有优缺点,在实际应用中需要根据具体的问题需求、二叉树的特点以及性能和空间的限制等因素来选择合适的实现方式。
242 59
|
4月前
|
编译器 C语言 C++
栈区的非法访问导致的死循环(x64)
这段内容主要分析了一段C语言代码在VS2022中形成死循环的原因,涉及栈区内存布局和数组越界问题。代码中`arr[15]`越界访问,修改了变量`i`的值,导致`for`循环条件始终为真,形成死循环。原因是VS2022栈区从低地址到高地址分配内存,`arr`数组与`i`相邻,`arr[15]`恰好覆盖`i`的地址。而在VS2019中,栈区先分配高地址再分配低地址,因此相同代码表现不同。这说明编译器对栈区内存分配顺序的实现差异会导致程序行为不一致,需避免数组越界以确保代码健壮性。
78 0
栈区的非法访问导致的死循环(x64)
232.用栈实现队列,225. 用队列实现栈
在232题中,通过两个栈(`stIn`和`stOut`)模拟队列的先入先出(FIFO)行为。`push`操作将元素压入`stIn`,`pop`和`peek`操作则通过将`stIn`的元素转移到`stOut`来实现队列的顺序访问。 225题则是利用单个队列(`que`)模拟栈的后入先出(LIFO)特性。通过多次调整队列头部元素的位置,确保弹出顺序符合栈的要求。`top`操作直接返回队列尾部元素,`empty`判断队列是否为空。 两题均仅使用基础数据结构操作,展示了栈与队列之间的转换逻辑。
|
9月前
|
存储 C语言 C++
【C++数据结构——栈与队列】顺序栈的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现顺序栈的基本运算。开始你的任务吧,祝你成功!​ 相关知识 初始化栈 销毁栈 判断栈是否为空 进栈 出栈 取栈顶元素 1.初始化栈 概念:初始化栈是为栈的使用做准备,包括分配内存空间(如果是动态分配)和设置栈的初始状态。栈有顺序栈和链式栈两种常见形式。对于顺序栈,通常需要定义一个数组来存储栈元素,并设置一个变量来记录栈顶位置;对于链式栈,需要定义节点结构,包含数据域和指针域,同时初始化栈顶指针。 示例(顺序栈): 以下是一个简单的顺序栈初始化示例,假设用C语言实现,栈中存储
374 77
|
8月前
|
算法 调度 C++
STL——栈和队列和优先队列
通过以上对栈、队列和优先队列的详细解释和示例,希望能帮助读者更好地理解和应用这些重要的数据结构。
195 11
|
8月前
|
网络协议 Linux Go
自己动手编写tcp/ip协议栈1:tcp包解析
学习tuntap中的tun的使用方法,并使用tun接口解析了ip包和tcp包,这是实现tcp/ip协议栈的第一步。
202 15
|
8月前
|
DataX
☀☀☀☀☀☀☀有关栈和队列应用的oj题讲解☼☼☼☼☼☼☼
### 简介 本文介绍了三种数据结构的实现方法:用两个队列实现栈、用两个栈实现队列以及设计循环队列。具体思路如下: 1. **用两个队列实现栈**: - 插入元素时,选择非空队列进行插入。 - 移除栈顶元素时,将非空队列中的元素依次转移到另一个队列,直到只剩下一个元素,然后弹出该元素。 - 判空条件为两个队列均为空。 2. **用两个栈实现队列**: - 插入元素时,选择非空栈进行插入。 - 移除队首元素时,将非空栈中的元素依次转移到另一个栈,再将这些元素重新放回原栈以保持顺序。 - 判空条件为两个栈均为空。
|
9月前
|
存储 C++ 索引
【C++数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】
【数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】初始化队列、销毁队列、判断队列是否为空、进队列、出队列等。本关任务:编写一个程序实现环形队列的基本运算。(6)出队列序列:yzopq2*(5)依次进队列元素:opq2*(6)出队列序列:bcdef。(2)依次进队列元素:abc。(5)依次进队列元素:def。(2)依次进队列元素:xyz。开始你的任务吧,祝你成功!(4)出队一个元素a。(4)出队一个元素x。
298 13
【C++数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】
|
11月前
|
自然语言处理 算法 Python
再谈递归下降解析器:构建一个简单的算术表达式解析器
本文介绍了递归下降解析器的原理与实现,重点讲解了如何使用Python构建一个简单的算术表达式解析器。通过定义文法、实现词法分析器和解析器类,最终实现了对基本算术表达式的解析与计算功能。
273 52
|
9月前
|
存储 C语言 C++
【C++数据结构——栈与队列】链栈的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现链栈的基本运算。开始你的任务吧,祝你成功!​ 相关知识 初始化栈 销毁栈 判断栈是否为空 进栈 出栈 取栈顶元素 初始化栈 概念:初始化栈是为栈的使用做准备,包括分配内存空间(如果是动态分配)和设置栈的初始状态。栈有顺序栈和链式栈两种常见形式。对于顺序栈,通常需要定义一个数组来存储栈元素,并设置一个变量来记录栈顶位置;对于链式栈,需要定义节点结构,包含数据域和指针域,同时初始化栈顶指针。 示例(顺序栈): 以下是一个简单的顺序栈初始化示例,假设用C语言实现,栈中存储整数,最大
158 9

热门文章

最新文章

推荐镜像

更多
  • DNS