Skip to content

Commit c747151

Browse files
committed
✨feat: add 1106
1 parent f1bf4f9 commit c747151

File tree

3 files changed

+175
-1
lines changed

3 files changed

+175
-1
lines changed

Index/栈.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
| [735. 行星碰撞](https://leetcode.cn/problems/asteroid-collision/) | [LeetCode 题解链接](https://leetcode.cn/problems/asteroid-collision/solution/by-ac_oier-p4qh/) | 中等 | 🤩🤩🤩🤩🤩 |
1414
| [856. 括号的分数](https://leetcode.cn/problems/score-of-parentheses/) | [LeetCode 题解链接](https://leetcode.cn/problems/score-of-parentheses/solution/by-ac_oier-0mhz/) | 中等 | 🤩🤩🤩🤩🤩 |
1515
| [946. 验证栈序列](https://leetcode.cn/problems/validate-stack-sequences/) | [LeetCode 题解链接](https://leetcode.cn/problems/validate-stack-sequences/solution/by-ac_oier-84qd/) | 中等 | 🤩🤩🤩🤩 |
16-
| [1190. 反转每对括号间的子串](https://leetcode-cn.com/problems/reverse-substrings-between-each-pair-of-parentheses/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/reverse-substrings-between-each-pair-of-parentheses/solution/gong-shui-san-xie-shi-yong-shuang-duan-d-r35q/) | 中等 | 🤩🤩🤩🤩🤩 |
16+
| [1106. 解析布尔表达式](https://leetcode.cn/problems/parsing-a-boolean-expression/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/tag-validator/solution/by-ac_oier-9l8z/) | 困难 | 🤩🤩🤩🤩 |
17+
| [1190. 反转每对括号间的子串](https://leetcode-cn.com/problems/reverse-substrings-between-each-pair-of-parentheses/) | [LeetCode 题解链接](https://leetcode.cn/problems/parsing-a-boolean-expression/solution/by-ac_oier-jr29/) | 中等 | 🤩🤩🤩🤩🤩 |
1718
| [1598. 文件夹操作日志搜集器](https://leetcode.cn/problems/crawler-log-folder/) | [LeetCode 题解链接](https://leetcode.cn/problems/crawler-log-folder/solution/by-ac_oier-24xb/) | 简单 | 🤩🤩🤩 |
1819
| [面试题 03.01. 三合一](https://leetcode-cn.com/problems/three-in-one-lcci/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/three-in-one-lcci/solution/yi-ti-shuang-jie-er-wei-shu-zu-yi-wei-sh-lih7/) | 简单 | 🤩🤩🤩 |
1920
| [面试题 02.05. 链表求和](https://leetcode-cn.com/problems/sum-lists-lcci/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/sum-lists-lcci/solution/by-ac_oier-v1zb/) | 中等 | 🤩🤩🤩 |

Index/表达式计算问题.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@
55
| [227. 基本计算器 II](https://leetcode-cn.com/problems/basic-calculator-ii/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/basic-calculator-ii/solution/shi-yong-shuang-zhan-jie-jue-jiu-ji-biao-c65k/) | 中等 | 🤩🤩🤩🤩 |
66
| [592. 分数加减运算](https://leetcode.cn/problems/fraction-addition-and-subtraction/) | [LeetCode 题解链接](https://leetcode.cn/problems/fraction-addition-and-subtraction/solution/by-ac_oier-rmpy/) | 中等 | 🤩🤩🤩🤩🤩 |
77
| [1006. 笨阶乘](https://leetcode-cn.com/problems/clumsy-factorial/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/clumsy-factorial/solution/gong-shui-san-xie-tong-yong-biao-da-shi-nngfp/) | 中等 | 🤩🤩🤩 |
8+
| [1106. 解析布尔表达式](https://leetcode.cn/problems/parsing-a-boolean-expression/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/tag-validator/solution/by-ac_oier-9l8z/) | 困难 | 🤩🤩🤩🤩 |
89

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
### 题目描述
2+
3+
这是 LeetCode 上的 **[1106. 解析布尔表达式](https://leetcode.cn/problems/parsing-a-boolean-expression/solution/by-ac_oier-jr29/)** ,难度为**困难**
4+
5+
Tag : 「栈」、「表达式计算」
6+
7+
8+
9+
给你一个以字符串形式表述的 布尔表达式 `(boolean) expression`,返回该式的运算结果。
10+
11+
有效的表达式需遵循以下约定:
12+
13+
* `"t"`,运算结果为 `True`
14+
* `"f"`,运算结果为 `False`
15+
* `"!(expr)"`,运算过程为对内部表达式 `expr` 进行逻辑 非的运算(`NOT`
16+
* `"&(expr1,expr2,...)"`,运算过程为对 `2` 个或以上内部表达式 `expr1, expr2, ...` 进行逻辑 与的运算(`AND`
17+
* `"|(expr1,expr2,...)"`,运算过程为对 `2` 个或以上内部表达式 `expr1, expr2, ...` 进行逻辑 或的运算(`OR`
18+
19+
20+
示例 1:
21+
```
22+
输入:expression = "!(f)"
23+
24+
输出:true
25+
```
26+
示例 2:
27+
```
28+
输入:expression = "|(f,t)"
29+
30+
输出:true
31+
```
32+
示例 3:
33+
```
34+
输入:expression = "&(t,f)"
35+
36+
输出:false
37+
```
38+
示例 4:
39+
```
40+
输入:expression = "|(&(t,f,t),!(t))"
41+
42+
输出:false
43+
```
44+
45+
提示:
46+
* $1 <= expression.length <= 20000$
47+
* `expression[i]``{'(', ')', '&', '|', '!', 't', 'f', ','}` 中的字符组成。
48+
* `expression` 是以上述形式给出的有效表达式,表示一个布尔值。
49+
50+
---
51+
52+
### 双栈
53+
54+
为了方便,我们令 `expression``s`
55+
56+
我们可以将 `t``f` 看做操作数,而 `|``&``!` 看做操作符,创建两个栈 `nums``ops` 分别对其进行存储。
57+
58+
剩余的 `()``,` 则只是优先级和分隔符,无须额外关注。
59+
60+
从前往后处理 `s`,根据当前处理的字符为何值进行分情况讨论:
61+
62+
* `,`:分隔符,直接跳过;
63+
* `t``f`:操作数,添加到 `nums` 栈中;
64+
* `|``&``!`:操作符,添加到 `ops` 栈中;
65+
* `(`:子表达式的左端点,为了在我们从「双栈」中取出数值和符号计算时,可以知道某个子表达式计算完成,需要记录一下。往 `nums` 追加一个占位符号 `-` 来代指;
66+
* `)`:子表达式的右端点,代表一个子表达式的结束。可从「双栈」中取出符号和数组进行计算(在 `ops` 中仅取栈顶元素,代表当前子表达式的操作符;而在 `nums` 中则取到代表左端点的占位元素 `-` 为止),并将结果重新放入 `nums` 中。
67+
68+
最后考虑如何计算最简表达式,考虑实现一个 `char calc(char a, char b, char op)` 函数,代表对操作数 `a``b` 执行 `op` 操作并进行结果返回。
69+
70+
实际上,在 `calc` 函数我们只区分 `|` 操作和其他操作即可。也就是说 `&``!` 均当做 `&` 来做,`!` 操作在计算完整个表达式后再翻转。
71+
72+
Java 代码:
73+
```Java
74+
class Solution {
75+
public boolean parseBoolExpr(String s) {
76+
Deque<Character> nums = new ArrayDeque<>(), ops = new ArrayDeque<>();
77+
for (char c : s.toCharArray()) {
78+
if (c == ',') continue;
79+
if (c == 't' || c == 'f') nums.addLast(c);
80+
if (c == '|' || c == '&' || c == '!') ops.addLast(c);
81+
if (c == '(') nums.addLast('-');
82+
if (c == ')') {
83+
char op = ops.pollLast(), cur = ' ';
84+
while (!nums.isEmpty() && nums.peekLast() != '-') {
85+
char top = nums.pollLast();
86+
cur = cur == ' ' ? top : calc(top, cur, op);
87+
}
88+
if (op == '!') cur = cur == 't' ? 'f' : 't';
89+
nums.pollLast(); nums.addLast(cur);
90+
}
91+
}
92+
return nums.peekLast() == 't';
93+
}
94+
char calc(char a, char b, char op) {
95+
boolean x = a == 't', y = b == 't';
96+
boolean ans = op == '|' ? x | y : x & y;
97+
return ans ? 't' : 'f';
98+
}
99+
}
100+
```
101+
TypeScript 代码:
102+
```TypeScript
103+
function parseBoolExpr(s: string): boolean {
104+
function calc(a: string, b: string, op: string): string {
105+
const x = a == 't', y = b == 't'
106+
const ans = op == '|' ? x || y : x && y
107+
return ans ? 't' : 'f'
108+
}
109+
const nums = new Array<string>(s.length).fill(''), ops = new Array<string>(s.length).fill('')
110+
let idx1 = 0, idx2 = 0
111+
for (const c of s) {
112+
if (c == ',') continue
113+
if (c == 't' || c == 'f') nums[idx1++] = c
114+
if (c == '|' || c == '&' || c == '!') ops[idx2++] = c
115+
if (c == '(') nums[idx1++] = '-'
116+
if (c == ')') {
117+
let op = ops[--idx2], cur = ' '
118+
while (idx1 > 0 && nums[idx1 - 1] != '-') {
119+
const top = nums[--idx1]
120+
cur = cur == ' ' ? top : calc(top, cur, op)
121+
}
122+
if (op == '!') cur = cur == 't' ? 'f' : 't'
123+
idx1--; nums[idx1++] = cur
124+
}
125+
}
126+
return nums[idx1 - 1] == 't'
127+
}
128+
```
129+
Python 代码:
130+
```Python
131+
class Solution:
132+
def parseBoolExpr(self, s: str) -> bool:
133+
def calc(a, b, op):
134+
x, y = a == 't', b == 't'
135+
ans = x | y if op == '|' else x & y
136+
return 't' if ans else 'f'
137+
nums, ops = [], []
138+
for c in s:
139+
if c == ',':
140+
continue
141+
if c == 't' or c == 'f':
142+
nums.append(c)
143+
if c == '|' or c == '&' or c == '!':
144+
ops.append(c)
145+
if c == '(':
146+
nums.append('-')
147+
if c == ')':
148+
op, cur = ops.pop(), ' '
149+
while nums and nums[-1] != '-':
150+
top = nums.pop()
151+
cur = top if cur == ' ' else calc(cur, top, op)
152+
if op == '!':
153+
cur = 't' if cur == 'f' else 'f'
154+
nums.pop()
155+
nums.append(cur)
156+
return nums[-1] == 't'
157+
```
158+
* 时间复杂度:$O(n)$
159+
* 空间复杂度:$O(n)$
160+
161+
---
162+
163+
### 最后
164+
165+
这是我们「刷穿 LeetCode」系列文章的第 `No.1106` 篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。
166+
167+
在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。
168+
169+
为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:https://github.com/SharingSource/LogicStack-LeetCode
170+
171+
在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。
172+

0 commit comments

Comments
 (0)