Skip to content

Commit ef5bf06

Browse files
committed
补充第 800 ~ 899 题的题目解析(增加 37 道题)
1 parent 2cd54a2 commit ef5bf06

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+4612
-2
lines changed

docs/00_preface/00_05_solutions_list.md

Lines changed: 41 additions & 1 deletion
Large diffs are not rendered by default.

docs/others/update_time.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
## 2026-01
22

3-
- 2026-01-05 补充第 700 ~ 799 题的题目解析(增加 5 道题)
3+
- 2026-01-07 补充第 800 ~ 899 题的题目解析(增加 37 道题)
4+
- 2026-01-05 补充第 700 ~ 799 题的题目解析(增加 8 道题)
45
- 2026-01-04 补充第 700 ~ 799 题的题目解析(增加 9 道题)
56
- 2026-01-03 补充第 700 ~ 799 题的题目解析(增加 27 道题)
67
- 2026-01-02 补充第 600 ~ 699 题的题目解析(增加 34 道题)
Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
# [0770. 基本计算器 IV](https://leetcode.cn/problems/basic-calculator-iv/)
2+
3+
- 标签:栈、递归、哈希表、数学、字符串
4+
- 难度:困难
5+
6+
## 题目链接
7+
8+
- [0770. 基本计算器 IV - 力扣](https://leetcode.cn/problems/basic-calculator-iv/)
9+
10+
## 题目大意
11+
12+
**描述**
13+
14+
给定一个表达式如 `expression = "e + 8 - a + 5"` 和一个求值映射,如 `{"e": 1}`(给定的形式为 `evalvars = ["e"]``evalints = [1]`
15+
16+
**要求**
17+
18+
返回表示简化表达式的标记列表,例如 `["-1*a","14"]`
19+
20+
- 表达式交替使用块和符号,每个块和符号之间有一个空格。
21+
- 块要么是括号中的表达式,要么是变量,要么是非负整数。
22+
- 变量是一个由小写字母组成的字符串(不包括数字)。请注意,变量可以是多个字母,并注意变量从不具有像 `"2x"``"-x"` 这样的前导系数或一元运算符。
23+
24+
表达式按通常顺序进行求值:先是括号,然后求乘法,再计算加法和减法。
25+
26+
- 例如,`expression = "1 + 2 * 3"` 的答案是 ["7"]
27+
28+
输出格式如下:
29+
30+
- 对于系数非零的每个自变量项,我们按字典排序的顺序将自变量写在一个项中。
31+
- 例如,我们永远不会写像 `"b*a*c"` 这样的项,只写 `"a*b*c"`
32+
- 项的次数等于被乘的自变量的数目,并计算重复项。我们先写出答案的最大次数项,用字典顺序打破关系,此时忽略词的前导系数。
33+
- 例如,`"a*a*b*c"` 的次数为 $4$。
34+
- 项的前导系数直接放在左边,用星号将它与变量分隔开(如果存在的话)。前导系数 $1$ 仍然要打印出来。
35+
- 格式良好的一个示例答案是 `["-2*a*a*a", "3*a*a*b", "3*b*b", "4*a", "5*c", "-6"]`
36+
- 系数为 $0$ 的项(包括常数项)不包括在内。
37+
- 例如,`"0"` 的表达式输出为 `[]`
38+
39+
注意:你可以假设给定的表达式均有效。所有中间结果都在区间 $[-2^{31}, 2^{31} - 1]$ 内。
40+
41+
**说明**
42+
43+
- $1 \le expression.length \le 250$。
44+
- expression 由小写英文字母,数字 '+', '-', '*', '(', ')', ' ' 组成。
45+
- expression 不包含任何前空格或后空格。
46+
- expression 中的所有符号都用一个空格隔开。
47+
- $0 \le evalvars.length \le 10^{3}$。
48+
- $1 \le evalvars[i].length \le 20$。
49+
- $evalvars[i]$ 由小写英文字母组成。
50+
- $evalints.length == evalvars.length$。
51+
- $-10^{3} \le evalints[i] \le 10^{3}$。
52+
53+
**示例**
54+
55+
- 示例 1:
56+
57+
```python
58+
输入:expression = "e + 8 - a + 5", evalvars = ["e"], evalints = [1]
59+
输出:["-1*a","14"]
60+
```
61+
62+
- 示例 2:
63+
64+
```python
65+
输入:expression = "e - 8 + temperature - pressure",
66+
evalvars = ["e", "temperature"], evalints = [1, 12]
67+
输出:["-1*pressure","5"]
68+
```
69+
70+
## 解题思路
71+
72+
### 思路 1:递归 + 哈希表 + 多项式运算
73+
74+
这道题要求实现一个支持变量的计算器,需要处理加减乘运算、括号和变量替换。
75+
76+
核心思路:
77+
78+
1. 定义多项式类,支持加减乘运算。
79+
2. 多项式用字典表示,键是变量的元组(按字典序排序),值是系数。
80+
3. 使用递归下降解析表达式。
81+
4. 先将给定的变量替换为常数,再进行计算。
82+
83+
算法步骤:
84+
85+
1. 创建多项式类 `Poly`,支持:
86+
- 加法:合并同类项。
87+
- 减法:系数取反后加法。
88+
- 乘法:分配律展开。
89+
2. 解析表达式:
90+
- 使用递归下降解析器处理括号、加减乘运算。
91+
- 遇到变量时,如果在求值映射中,替换为常数;否则保留为变量。
92+
3. 格式化输出:
93+
- 按次数从高到低、字典序排序。
94+
- 格式化每一项。
95+
96+
### 思路 1:代码
97+
98+
```python
99+
class Solution:
100+
def basicCalculatorIV(self, expression: str, evalvars: List[str], evalints: List[int]) -> List[str]:
101+
from collections import Counter
102+
103+
# 创建变量求值映射
104+
eval_map = dict(zip(evalvars, evalints))
105+
106+
# 多项式类
107+
class Poly:
108+
def __init__(self, terms=None):
109+
# terms: {变量元组: 系数}
110+
self.terms = Counter(terms) if terms else Counter()
111+
112+
def __add__(self, other):
113+
result = Poly(self.terms)
114+
for key, val in other.terms.items():
115+
result.terms[key] += val
116+
return result
117+
118+
def __sub__(self, other):
119+
result = Poly(self.terms)
120+
for key, val in other.terms.items():
121+
result.terms[key] -= val
122+
return result
123+
124+
def __mul__(self, other):
125+
result = Poly()
126+
for k1, v1 in self.terms.items():
127+
for k2, v2 in other.terms.items():
128+
# 合并变量(按字典序排序)
129+
key = tuple(sorted(k1 + k2))
130+
result.terms[key] += v1 * v2
131+
return result
132+
133+
def to_list(self):
134+
# 转换为输出格式
135+
# 删除系数为 0 的项
136+
items = [(k, v) for k, v in self.terms.items() if v != 0]
137+
# 排序:先按次数降序,再按字典序
138+
items.sort(key=lambda x: (-len(x[0]), x[0]))
139+
140+
result = []
141+
for vars_tuple, coef in items:
142+
if vars_tuple:
143+
result.append(f"{coef}*{'*'.join(vars_tuple)}")
144+
else:
145+
result.append(str(coef))
146+
return result
147+
148+
# 解析表达式
149+
tokens = expression.replace('(', ' ( ').replace(')', ' ) ').split()
150+
151+
def parse():
152+
"""解析加减表达式"""
153+
nonlocal idx
154+
left = parse_term()
155+
156+
while idx < len(tokens) and tokens[idx] in ['+', '-']:
157+
op = tokens[idx]
158+
idx += 1
159+
right = parse_term()
160+
if op == '+':
161+
left = left + right
162+
else:
163+
left = left - right
164+
165+
return left
166+
167+
def parse_term():
168+
"""解析乘法表达式"""
169+
nonlocal idx
170+
left = parse_factor()
171+
172+
while idx < len(tokens) and tokens[idx] == '*':
173+
idx += 1
174+
right = parse_factor()
175+
left = left * right
176+
177+
return left
178+
179+
def parse_factor():
180+
"""解析因子(数字、变量或括号表达式)"""
181+
nonlocal idx
182+
token = tokens[idx]
183+
idx += 1
184+
185+
if token == '(':
186+
result = parse()
187+
idx += 1 # 跳过 ')'
188+
return result
189+
elif token.lstrip('-').isdigit():
190+
# 数字
191+
return Poly({(): int(token)})
192+
else:
193+
# 变量
194+
if token in eval_map:
195+
return Poly({(): eval_map[token]})
196+
else:
197+
return Poly({(token,): 1})
198+
199+
idx = 0
200+
poly = parse()
201+
return poly.to_list()
202+
```
203+
204+
### 思路 1:复杂度分析
205+
206+
- **时间复杂度**:$O(n \times m)$,其中 $n$ 是表达式的长度,$m$ 是多项式项的数量。解析和计算都需要遍历表达式。
207+
- **空间复杂度**:$O(m)$,需要存储多项式的所有项。

docs/solutions/0700-0799/index.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
- [0753. 破解保险箱](https://github.com/ITCharge/AlgoNote/tree/main/docs/solutions/0700-0799/cracking-the-safe.md)
4949
- [0754. 到达终点数字](https://github.com/ITCharge/AlgoNote/tree/main/docs/solutions/0700-0799/reach-a-number.md)
5050
- [0756. 金字塔转换矩阵](https://github.com/ITCharge/AlgoNote/tree/main/docs/solutions/0700-0799/pyramid-transition-matrix.md)
51+
- [0757. 设置交集大小至少为2](https://github.com/ITCharge/AlgoNote/tree/main/docs/solutions/0700-0799/set-intersection-size-at-least-two.md)
5152
- [0758. 字符串中的加粗单词](https://github.com/ITCharge/AlgoNote/tree/main/docs/solutions/0700-0799/bold-words-in-string.md)
5253
- [0762. 二进制表示中质数个计算置位](https://github.com/ITCharge/AlgoNote/tree/main/docs/solutions/0700-0799/prime-number-of-set-bits-in-binary-representation.md)
5354
- [0763. 划分字母区间](https://github.com/ITCharge/AlgoNote/tree/main/docs/solutions/0700-0799/partition-labels.md)
@@ -57,6 +58,7 @@
5758
- [0767. 重构字符串](https://github.com/ITCharge/AlgoNote/tree/main/docs/solutions/0700-0799/reorganize-string.md)
5859
- [0768. 最多能完成排序的块 II](https://github.com/ITCharge/AlgoNote/tree/main/docs/solutions/0700-0799/max-chunks-to-make-sorted-ii.md)
5960
- [0769. 最多能完成排序的块](https://github.com/ITCharge/AlgoNote/tree/main/docs/solutions/0700-0799/max-chunks-to-make-sorted.md)
61+
- [0770. 基本计算器 IV](https://github.com/ITCharge/AlgoNote/tree/main/docs/solutions/0700-0799/basic-calculator-iv.md)
6062
- [0771. 宝石与石头](https://github.com/ITCharge/AlgoNote/tree/main/docs/solutions/0700-0799/jewels-and-stones.md)
6163
- [0773. 滑动谜题](https://github.com/ITCharge/AlgoNote/tree/main/docs/solutions/0700-0799/sliding-puzzle.md)
6264
- [0775. 全局倒置与局部倒置](https://github.com/ITCharge/AlgoNote/tree/main/docs/solutions/0700-0799/global-and-local-inversions.md)
@@ -65,6 +67,7 @@
6567
- [0779. 第K个语法符号](https://github.com/ITCharge/AlgoNote/tree/main/docs/solutions/0700-0799/k-th-symbol-in-grammar.md)
6668
- [0780. 到达终点](https://github.com/ITCharge/AlgoNote/tree/main/docs/solutions/0700-0799/reaching-points.md)
6769
- [0781. 森林中的兔子](https://github.com/ITCharge/AlgoNote/tree/main/docs/solutions/0700-0799/rabbits-in-forest.md)
70+
- [0782. 变为棋盘](https://github.com/ITCharge/AlgoNote/tree/main/docs/solutions/0700-0799/transform-to-chessboard.md)
6871
- [0783. 二叉搜索树节点最小距离](https://github.com/ITCharge/AlgoNote/tree/main/docs/solutions/0700-0799/minimum-distance-between-bst-nodes.md)
6972
- [0784. 字母大小写全排列](https://github.com/ITCharge/AlgoNote/tree/main/docs/solutions/0700-0799/letter-case-permutation.md)
7073
- [0785. 判断二分图](https://github.com/ITCharge/AlgoNote/tree/main/docs/solutions/0700-0799/is-graph-bipartite.md)
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
# [0757. 设置交集大小至少为2](https://leetcode.cn/problems/set-intersection-size-at-least-two/)
2+
3+
- 标签:贪心、数组、排序
4+
- 难度:困难
5+
6+
## 题目链接
7+
8+
- [0757. 设置交集大小至少为2 - 力扣](https://leetcode.cn/problems/set-intersection-size-at-least-two/)
9+
10+
## 题目大意
11+
12+
**描述**
13+
14+
给定一个二维整数数组 $intervals$ ,其中 $intervals[i] = [starti, endi]$ 表示从 $starti$ 到 $endi$ 的所有整数,包括 $starti$ 和 $endi$。
15+
16+
「包含集合」是一个名为 $nums$ 的数组,并满足 $intervals$ 中的每个区间都「至少」有「两个」整数在 $nums$ 中。
17+
18+
- 例如,如果 $intervals = [[1,3], [3,7], [8,9]]$,那么 $[1,2,4,7,8,9]$ 和 $[2,3,4,8,9]$ 都符合「包含集合」的定义。
19+
20+
**要求**
21+
22+
返回包含集合可能的最小大小。
23+
24+
**说明**
25+
26+
- $1 \le intervals.length \le 3000$。
27+
- $intervals[i].length == 2$。
28+
- $0 \le starti \lt endi \le 10^{8}$。
29+
30+
**示例**
31+
32+
- 示例 1:
33+
34+
```python
35+
输入:intervals = [[1,3],[3,7],[8,9]]
36+
输出:5
37+
解释:nums = [2, 3, 4, 8, 9].
38+
可以证明不存在元素数量为 4 的包含集合。
39+
```
40+
41+
- 示例 2:
42+
43+
```python
44+
输入:intervals = [[1,3],[1,4],[2,5],[3,5]]
45+
输出:3
46+
解释:nums = [2, 3, 4].
47+
可以证明不存在元素数量为 2 的包含集合。
48+
```
49+
50+
## 解题思路
51+
52+
### 思路 1:贪心 + 排序
53+
54+
贪心策略:按照区间的右端点排序,优先选择右端点较小的区间。
55+
56+
**实现步骤**
57+
58+
1. 按照区间的右端点升序排序,如果右端点相同,按左端点降序排序。
59+
2. 维护一个集合 $S$,初始为空。
60+
3. 遍历每个区间 $[start, end]$:
61+
- 统计 $S$ 中在该区间内的元素个数 $count$。
62+
- 如果 $count < 2$,需要添加 $2 - count$ 个元素。
63+
- 贪心地选择尽可能靠右的元素($end - 1$ 和 $end$),以便覆盖更多后续区间。
64+
4. 返回集合的大小。
65+
66+
### 思路 1:代码
67+
68+
```python
69+
class Solution:
70+
def intersectionSizeTwo(self, intervals: List[List[int]]) -> int:
71+
# 按右端点升序排序,右端点相同时按左端点降序排序
72+
intervals.sort(key=lambda x: (x[1], -x[0]))
73+
74+
result = []
75+
76+
for start, end in intervals:
77+
# 统计 result 中在 [start, end] 范围内的元素个数
78+
count = sum(1 for x in result if start <= x <= end)
79+
80+
# 需要添加的元素个数
81+
need = 2 - count
82+
83+
if need <= 0:
84+
continue
85+
86+
# 贪心地选择尽可能靠右的元素
87+
if need == 1:
88+
# 添加 end
89+
result.append(end)
90+
else: # need == 2
91+
# 添加 end-1 和 end
92+
result.append(end - 1)
93+
result.append(end)
94+
95+
return len(result)
96+
```
97+
98+
### 思路 1:复杂度分析
99+
100+
- **时间复杂度**:$O(n^2)$,其中 $n$ 是区间的数量。排序需要 $O(n \log n)$,遍历每个区间需要 $O(n)$,每次统计需要 $O(n)$。
101+
- **空间复杂度**:$O(n)$,存储结果的空间。

0 commit comments

Comments
 (0)