Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit b56a103

Browse files
✨feat: add 736
1 parent b5f7def commit b56a103

File tree

3 files changed

+161
-0
lines changed

3 files changed

+161
-0
lines changed

‎Index/DFS.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
| [677. 键值映射](https://leetcode-cn.com/problems/map-sum-pairs/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/map-sum-pairs/solution/gong-shui-san-xie-jie-he-dfs-de-trie-yun-i4xa/) | 中等 | 🤩🤩🤩🤩 |
3434
| [690. 员工的重要性](https://leetcode-cn.com/problems/employee-importance/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/employee-importance/solution/gong-shui-san-xie-yi-ti-shuang-jie-di-gu-s79x/) | 简单 | 🤩🤩🤩 |
3535
| [691. 贴纸拼词](https://leetcode.cn/problems/stickers-to-spell-word/) | [LeetCode 题解链接](https://leetcode.cn/problems/stickers-to-spell-word/solution/by-ac_oier-5vv3/) | 困难 | 🤩🤩🤩🤩 |
36+
| [736. Lisp 语法解析](https://leetcode.cn/problems/parse-lisp-expression/) | [LeetCode 题解链接](https://leetcode.cn/problems/parse-lisp-expression/solution/by-ac_oier-i7w1/) | 困难 | 🤩🤩🤩🤩 |
3637
| [778. 水位上升的泳池中游泳](https://leetcode-cn.com/problems/swim-in-rising-water/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/swim-in-rising-water/solution/gong-shui-san-xie-yi-ti-shuang-jie-krusk-7c6o/) | 困难 | 🤩🤩🤩 |
3738
| [783. 二叉搜索树节点最小距离](https://leetcode-cn.com/problems/minimum-distance-between-bst-nodes/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/minimum-distance-between-bst-nodes/solution/gong-shui-san-xie-yi-ti-san-jie-shu-de-s-7r17/) | 简单 | 🤩🤩🤩 |
3839
| [869. 重新排序得到 2 的幂](https://leetcode-cn.com/problems/reordered-power-of-2/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/reordered-power-of-2/solution/gong-shui-san-xie-yi-ti-shuang-jie-dfs-c-3s1e/) | 中等 | 🤩🤩🤩🤩 |

‎Index/哈希表.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
| [710. 黑名单中的随机数](https://leetcode.cn/problems/random-pick-with-blacklist/) | [LeetCode 题解链接](https://leetcode.cn/problems/random-pick-with-blacklist/solution/by-ac_oier-2rww/) | 困难 | 🤩🤩🤩🤩 |
4444
| [726. 原子的数量](https://leetcode-cn.com/problems/number-of-atoms/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/number-of-atoms/solution/gong-shui-san-xie-shi-yong-xiao-ji-qiao-l5ak4/) | 困难 | 🤩🤩🤩🤩 |
4545
| [728. 自除数](https://leetcode-cn.com/problems/self-dividing-numbers/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/self-dividing-numbers/solution/by-ac_oier-pvb1/) | 简单 | 🤩🤩🤩 |
46+
| [736. Lisp 语法解析](https://leetcode.cn/problems/parse-lisp-expression/) | [LeetCode 题解链接](https://leetcode.cn/problems/parse-lisp-expression/solution/by-ac_oier-i7w1/) | 困难 | 🤩🤩🤩🤩 |
4647
| [846. 一手顺子](https://leetcode-cn.com/problems/hand-of-straights/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/hand-of-straights/solution/gong-shui-san-xie-shu-ju-jie-gou-mo-ni-t-4hxw/) | 中等 | 🤩🤩🤩 |
4748
| [869. 重新排序得到 2 的幂](https://leetcode-cn.com/problems/reordered-power-of-2/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/reordered-power-of-2/solution/gong-shui-san-xie-yi-ti-shuang-jie-dfs-c-3s1e/) | 中等 | 🤩🤩🤩🤩 |
4849
| [884. 两句话中的不常见单词](https://leetcode-cn.com/problems/uncommon-words-from-two-sentences/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/uncommon-words-from-two-sentences/solution/gong-shui-san-xie-shu-ju-jie-gou-mo-ni-t-wwam/) | 简单 | 🤩🤩🤩🤩🤩 |
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
### 题目描述
2+
3+
这是 LeetCode 上的 **[736. Lisp 语法解析](https://leetcode.cn/problems/parse-lisp-expression/solution/by-ac_oier-i7w1/)** ,难度为 **困难**
4+
5+
Tag : 「DFS」、「模拟」、「哈希表」
6+
7+
8+
9+
给你一个类似 `Lisp` 语句的字符串表达式 `expression`,求出其计算结果。
10+
11+
表达式语法如下所示:
12+
13+
* 表达式可以为整数,`let` 表达式,`add` 表达式,`mult` 表达式,或赋值的变量。表达式的结果总是一个整数。
14+
* (整数可以是正整数、负整数、0ドル$)
15+
* `let` 表达式采用 `"(let v1 e1 v2 e2 ... vn en expr)"` 的形式,其中 `let` 总是以字符串 `"let"`来表示,接下来会跟随一对或多对交替的变量和表达式,也就是说,第一个变量 `v1`被分配为表达式 `e1` 的值,第二个变量 `v2` 被分配为表达式 `e2` 的值,依次类推;最终 `let` 表达式的值为 `expr` 表达式的值。
16+
* `add` 表达式表示为 `"(add e1 e2)"` ,其中 `add` 总是以字符串 `"add"` 来表示,该表达式总是包含两个表达式 `e1``e2` ,最终结果是 `e1` 表达式的值与 `e2` 表达式的值之 和 。
17+
* `mult` 表达式表示为 `"(mult e1 e2)"` ,其中 `mult` 总是以字符串 `"mult"` 表示,该表达式总是包含两个表达式 `e1`、e2,最终结果是 `e1` 表达式的值与 `e2` 表达式的值之 积 。
18+
* 在该题目中,变量名以小写字符开始,之后跟随 0ドル$ 个或多个小写字符或数字。为了方便,`"add"` ,`"let"` ,`"mult"` 会被定义为 `"关键字" ,不会用作变量名。
19+
* 最后,要说一下作用域的概念。计算变量名所对应的表达式时,在计算上下文中,首先检查最内层作用域(按括号计),然后按顺序依次检查外部作用域。测试用例中每一个表达式都是合法的。有关作用域的更多详细信息,请参阅示例。
20+
21+
示例 1:
22+
23+
输入:expression = "(let x 2 (mult x (let x 3 y 4 (add x y))))"
24+
输出:14
25+
解释:
26+
计算表达式 (add x y), 在检查变量 x 值时,
27+
在变量的上下文中由最内层作用域依次向外检查。
28+
首先找到 x = 3, 所以此处的 x 值是 3 。
29+
示例 2:
30+
```
31+
输入:expression = "(let x 3 x 2 x)"
32+
33+
输出:2
34+
35+
解释:let 语句中的赋值运算按顺序处理即可。
36+
```
37+
示例 3:
38+
```
39+
输入:expression = "(let x 1 y 2 x (add x y) (add x y))"
40+
41+
输出:5
42+
43+
解释:
44+
第一个 (add x y) 计算结果是 3,并且将此值赋给了 x 。
45+
第二个 (add x y) 计算结果是 3 + 2 = 5 。
46+
```
47+
48+
提示:
49+
* 1ドル <= expression.length <= 2000$
50+
* `exprssion` 中不含前导和尾随空格
51+
* `expressoin` 中的不同部分(`token`)之间用单个空格进行分隔
52+
* 答案和所有中间计算结果都符合 `32-bit` 整数范围
53+
54+
---
55+
56+
### DFS 模拟
57+
58+
今天身体不舒服,不写太详细,题目不难,大家结合代码看吧。
59+
60+
设计函数 `int dfs(int l, int r, Map<String, Integer> map)` 函数,代表计算 $s[l...r]$ 的结果,答案为 `dfs(0,n-1,map)`,其中 $n$ 为字符串的长度。
61+
62+
根据传入的 $[l, r]$ 是否为表达式分情况讨论:
63+
64+
* 若 $s[l] = (,ドル说明是表达式,此时从 $l$ 开始往后取,取到空格为止(假设位置为 `idx`),从而得到操作 `op`(其中 `op``let``add``mult` 三者之一),此时 `op` 对应参数为 $[idx + 1, r - 1],ドル也就是需要跳过位置 $r$(即跳过 `op` 对应的 `)` 符号);
65+
66+
再根据 `op` 为何种操作进一步处理,我们设计一个「传入左端点找右端点」的函数 `int getRight(int left, int end)`,含义为从 `left` 出发,一直往右找(不超过 `end`),直到取得合法的「子表达式」或「对应的值」。
67+
68+
```Java
69+
// 对于 getRight 函数作用,给大家举个 🌰 理解吧,其实就是从 left 出发,找到合法的「子表达式」或「值」为止
70+
71+
// (let x 2 (mult x (let x 3 y 4 (add x y))))
72+
// a b
73+
// 传入 a 返回 b,代表 [a, b) 表达式为 (mult x (let x 3 y 4 (add x y)))
74+
75+
// (let x 2 (mult x (let x 3 y 4 (add x y))))
76+
// ab
77+
// 传入 a 返回 b,代表 [a, b) 表达式为 x
78+
```
79+
80+
* 否则 $s[l...r]$ 不是表达式,通过判断 $s[l...r]$ 是否有被哈希表记录来得知结果:若在哈希表中有记录,结果为哈希表中的映射值,否则结果为本身所代表的数值。
81+
82+
需要注意,根据「作用域」的定义,我们不能使用全局哈希表,而要在每一层递归时,传入 `clone` 出来的 `map`。
83+
84+
代码:
85+
```Java
86+
class Solution {
87+
char[] cs;
88+
String s;
89+
public int evaluate(String _s) {
90+
s = _s;
91+
cs = s.toCharArray();
92+
return dfs(0, cs.length - 1, new HashMap<>());
93+
}
94+
int dfs(int l, int r, Map<String, Integer> map) {
95+
if (cs[l] == '(') {
96+
int idx = l;
97+
while (cs[idx] != ' ') idx++;
98+
String op = s.substring(l + 1, idx);
99+
r--; // 判别为 "(let"、"(add" 或 "(mult" 后,跳过对应的 ")"
100+
if (op.equals("let")) {
101+
for (int i = idx + 1; i <= r; ) {
102+
int j = getRight(i, r);
103+
String key = s.substring(i, j);
104+
if (j >= r) return dfs(i, j - 1, new HashMap<>(map));
105+
j++; i = j;
106+
j = getRight(i, r);
107+
int value = dfs(i, j - 1, new HashMap<>(map));
108+
map.put(key, value);
109+
i = j + 1;
110+
}
111+
return -1; // never
112+
} else if (op.equals("add")) {
113+
int j = getRight(idx + 1, r);
114+
int a = dfs(idx + 1, j - 1, new HashMap<>(map)), b = dfs(j + 1, r, new HashMap<>(map));
115+
return a + b;
116+
} else {
117+
int j = getRight(idx + 1, r);
118+
int a = dfs(idx + 1, j - 1, new HashMap<>(map)), b = dfs(j + 1, r, new HashMap<>(map));
119+
return a * b;
120+
}
121+
} else {
122+
String cur = s.substring(l, r + 1);
123+
if (map.containsKey(cur)) return map.get(cur);
124+
return Integer.parseInt(cur);
125+
}
126+
}
127+
int getRight(int left, int end) {
128+
int right = left, score = 0;
129+
while (right <= end) {
130+
if (cs[right] == '(') {
131+
score++; right++;
132+
} else if (cs[right] == ')') {
133+
score--; right++;
134+
} else if (cs[right] == ' ') {
135+
if (score == 0) break;
136+
right++;
137+
} else {
138+
right++;
139+
}
140+
}
141+
return right;
142+
}
143+
}
144+
```
145+
* 时间复杂度:除对表达式进行递归划分以外,还存在对 `map` 的每层拷贝操作,复杂度为 $O(n^2)$
146+
* 空间复杂度:$O(n)$
147+
148+
---
149+
150+
### 最后
151+
152+
这是我们「刷穿 LeetCode」系列文章的第 `No.736` 篇,系列开始于 2021年01月01日,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。
153+
154+
在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。
155+
156+
为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:https://github.com/SharingSource/LogicStack-LeetCode
157+
158+
在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。
159+

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /