Skip to content

Commit 254fed8

Browse files
committed
补全第 200 ~ 299 题的题目解析(增加 33 道题)
1 parent ac078ef commit 254fed8

36 files changed

+3601
-1
lines changed

docs/00_preface/00_05_solutions_list.md

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

docs/others/update_time.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
## 2025-10
22

3+
- 2025-10-20 补全第 200 ~ 299 题的题目解析(增加 33 道题)
34
- 2025-10-19 补充第 200 ~ 299 题的题目解析(增加 8 道题)
45
- 2025-10-17 补全第 100 ~ 199 题的题目解析(增加 12 道题)
56
- 2025-10-16 补全第 1 ~ 99 题的题目解析(增加 13 道题)
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
# [0269. 火星词典](https://leetcode.cn/problems/alien-dictionary/)
2+
3+
- 标签:深度优先搜索、广度优先搜索、图、拓扑排序、数组、字符串
4+
- 难度:困难
5+
6+
## 题目链接
7+
8+
- [0269. 火星词典 - 力扣](https://leetcode.cn/problems/alien-dictionary/)
9+
10+
## 题目大意
11+
12+
**描述**
13+
14+
现有一种使用英语字母的火星语言,这门语言的字母顺序对你来说是未知的。
15+
16+
给定一个来自这种外星语言字典的字符串列表 $words$ ,$words$ 中的字符串已经「按这门新语言的字典序进行了排序」。
17+
18+
**要求**
19+
20+
如果这种说法是错误的,并且给出的 $words$ 不能对应任何字母的顺序,则返回 `""`
21+
22+
否则,返回一个按新语言规则的「字典递增顺序」排序的独特字符串。如果有多个解决方案,则返回其中任意一个。
23+
24+
**说明**
25+
26+
- $1 \le words.length \le 10^{3}$。
27+
- $1 \le words[i].length \le 10^{3}$。
28+
- $words[i]$ 仅由小写英文字母组成。
29+
30+
**示例**
31+
32+
- 示例 1:
33+
34+
```python
35+
输入:words = ["wrt","wrf","er","ett","rftt"]
36+
输出:"wertf"
37+
```
38+
39+
- 示例 2:
40+
41+
```python
42+
输入:words = ["z","x"]
43+
输出:"zx"
44+
```
45+
46+
## 解题思路
47+
48+
### 思路 1:拓扑排序 + 广度优先搜索
49+
50+
使用拓扑排序来解决这个问题。我们需要构建一个图来表示字母之间的相对顺序关系,然后使用拓扑排序来找到字母的正确顺序。
51+
52+
具体步骤如下:
53+
54+
1. 构建图:遍历相邻的单词对 $(words[i], words[i+1])$,找到第一个不同的字符,建立字符 $c_1$ 到字符 $c_2$ 的边,表示 $c_1$ 在 $c_2$ 之前。
55+
2. 计算入度:统计每个字符的入度 $indegree[c]$。
56+
3. 拓扑排序:使用广度优先搜索,从入度为 $0$ 的字符开始,逐步构建字母顺序。
57+
4. 验证结果:检查是否所有字符都被包含在结果中。
58+
59+
关键点:
60+
61+
- 如果存在环,说明无法确定字母顺序,返回空字符串。
62+
- 如果拓扑排序后仍有字符未被访问,说明存在环。
63+
- 需要处理所有出现的字符,包括那些没有相对顺序关系的字符。
64+
65+
### 思路 1:代码
66+
67+
```python
68+
class Solution:
69+
def alienOrder(self, words: List[str]) -> str:
70+
# 构建图:字符到其后继字符的映射
71+
graph = {}
72+
# 统计每个字符的入度
73+
indegree = {}
74+
75+
# 初始化所有出现的字符
76+
for word in words:
77+
for char in word:
78+
if char not in graph:
79+
graph[char] = set()
80+
if char not in indegree:
81+
indegree[char] = 0
82+
83+
# 构建图:比较相邻单词
84+
for i in range(len(words) - 1):
85+
word1, word2 = words[i], words[i + 1]
86+
min_len = min(len(word1), len(word2))
87+
88+
# 检查是否存在前缀关系
89+
for j in range(min_len):
90+
if word1[j] != word2[j]:
91+
# 找到第一个不同的字符,建立边关系
92+
char1, char2 = word1[j], word2[j]
93+
if char2 not in graph[char1]:
94+
graph[char1].add(char2)
95+
indegree[char2] += 1
96+
break
97+
else:
98+
# 如果所有字符都相同,但第一个单词更长,则无效
99+
if len(word1) > len(word2):
100+
return ""
101+
102+
# 拓扑排序:使用广度优先搜索
103+
queue = []
104+
# 找到所有入度为 0 的字符
105+
for char in indegree:
106+
if indegree[char] == 0:
107+
queue.append(char)
108+
109+
result = []
110+
while queue:
111+
char = queue.pop(0)
112+
result.append(char)
113+
114+
# 处理当前字符的所有后继字符
115+
for next_char in graph[char]:
116+
indegree[next_char] -= 1
117+
if indegree[next_char] == 0:
118+
queue.append(next_char)
119+
120+
# 检查是否所有字符都被访问(无环)
121+
if len(result) != len(indegree):
122+
return ""
123+
124+
return ''.join(result)
125+
```
126+
127+
### 思路 1:复杂度分析
128+
129+
- **时间复杂度**:$O(C)$,其中 $C$ 是所有单词中字符的总数。需要遍历所有字符来构建图和进行拓扑排序。
130+
- **空间复杂度**:$O(1)$,因为字符集大小固定为 $26$ 个字母,所以图的大小和入度数组都是常数级别。
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
# [0224. 基本计算器](https://leetcode.cn/problems/basic-calculator/)
2+
3+
- 标签:栈、递归、数学、字符串
4+
- 难度:困难
5+
6+
## 题目链接
7+
8+
- [0224. 基本计算器 - 力扣](https://leetcode.cn/problems/basic-calculator/)
9+
10+
## 题目大意
11+
12+
**描述**
13+
14+
给定一个字符串表达式 $s$。
15+
16+
**要求**
17+
18+
实现一个基本计算器来计算并返回它的值。
19+
20+
**说明**
21+
22+
- 注意:不允许使用任何将字符串作为数学表达式计算的内置函数,比如 `eval()`
23+
- $1 \le s.length \le 3 \times 10^{5}$。
24+
- $s$ 由数字、`'+'``'-'``'('、')'`、和 `' '` 组成。
25+
- $s$ 表示一个有效的表达式。
26+
- `'+'` 不能用作一元运算(例如, `"+1"``"+(2 + 3)"` 无效)。
27+
- `'-'` 可以用作一元运算(即 `"-1"``"-(2 + 3)"` 是有效的)。
28+
- 输入中不存在两个连续的操作符。
29+
- 每个数字和运行的计算将适合于一个有符号的 32 位整数。
30+
31+
**示例**
32+
33+
- 示例 1:
34+
35+
```python
36+
输入:s = "1 + 1"
37+
输出:2
38+
```
39+
40+
- 示例 2:
41+
42+
```python
43+
输入:s = " 2-1 + 2 "
44+
输出:3
45+
```
46+
47+
## 解题思路
48+
49+
### 思路 1:栈 + 递归
50+
51+
使用栈来处理括号和运算符的优先级。由于只有加法和减法,我们可以通过维护一个符号栈来处理括号内的运算。
52+
53+
具体步骤如下:
54+
55+
1. 使用栈 $stack$ 来存储当前的计算结果和符号。
56+
2. 使用变量 $result$ 来存储当前的计算结果。
57+
3. 使用变量 $sign$ 来存储当前的符号($+1$ 或 $-1$)。
58+
4. 遍历字符串 $s$:
59+
- 如果遇到数字,则计算完整的数字值。
60+
- 如果遇到 `+`,则设置 $sign = 1$。
61+
- 如果遇到 `-`,则设置 $sign = -1$。
62+
- 如果遇到 `(`,则将当前的 $result$ 和 $sign$ 压入栈中,并重置 $result$ 和 $sign$。
63+
- 如果遇到 `)`,则从栈中弹出之前的结果和符号,与当前结果进行运算
64+
5. 最后返回 $result$。
65+
66+
这种方法可以正确处理括号的嵌套和运算符的优先级。
67+
68+
### 思路 1:代码
69+
70+
```python
71+
class Solution:
72+
def calculate(self, s: str) -> int:
73+
# 使用栈来处理括号和运算符
74+
stack = []
75+
result = 0 # 当前计算结果
76+
sign = 1 # 当前符号,1 表示正数,-1 表示负数
77+
78+
i = 0
79+
while i < len(s):
80+
char = s[i]
81+
82+
if char.isdigit():
83+
# 计算完整的数字
84+
num = 0
85+
while i < len(s) and s[i].isdigit():
86+
num = num * 10 + int(s[i])
87+
i += 1
88+
i -= 1 # 回退一位,因为外层循环会 i += 1
89+
result += sign * num
90+
91+
elif char == '+':
92+
sign = 1
93+
94+
elif char == '-':
95+
sign = -1
96+
97+
elif char == '(':
98+
# 遇到左括号,将当前结果和符号压入栈
99+
stack.append(result)
100+
stack.append(sign)
101+
# 重置结果和符号
102+
result = 0
103+
sign = 1
104+
105+
elif char == ')':
106+
# 遇到右括号,从栈中弹出之前的结果和符号
107+
result *= stack.pop() # 弹出符号
108+
result += stack.pop() # 弹出之前的结果
109+
110+
# 跳过空格
111+
i += 1
112+
113+
return result
114+
```
115+
116+
### 思路 1:复杂度分析
117+
118+
- **时间复杂度**:$O(n)$,其中 $n$ 是字符串 $s$ 的长度。需要遍历字符串一次。
119+
- **空间复杂度**:$O(n)$,最坏情况下栈的深度为 $O(n)$,例如当所有括号都嵌套时。
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
# [0296. 最佳的碰头地点](https://leetcode.cn/problems/best-meeting-point/)
2+
3+
- 标签:数组、数学、矩阵、排序
4+
- 难度:困难
5+
6+
## 题目链接
7+
8+
- [0296. 最佳的碰头地点 - 力扣](https://leetcode.cn/problems/best-meeting-point/)
9+
10+
## 题目大意
11+
12+
**描述**
13+
14+
给定一个 $m \times n$ 的二进制网格 $grid$,其中 $1$ 表示某个朋友的家所处的位置。
15+
16+
**要求**
17+
18+
返回「最小的」总行走距离。
19+
20+
**说明**
21+
22+
- 总行走距离:指的是朋友们家到碰头地点的距离之和。使用「曼哈顿距离」来计算,其中 $distance(p1, p2) = |p2.x - p1.x| + |p2.y - p1.y|$。
23+
- $m == grid.length$。
24+
- $n == grid[i].length$。
25+
- $1 \le m, n \le 200$。
26+
- $grid[i][j]$ 等于 $0$ 或者 $1$。
27+
- $grid$ 中 至少 有两个朋友。
28+
29+
**示例**
30+
31+
- 示例 1:
32+
33+
![](https://assets.leetcode.com/uploads/2021/03/14/meetingpoint-grid.jpg)
34+
35+
```python
36+
输入: grid = [[1,0,0,0,1],[0,0,0,0,0],[0,0,1,0,0]]
37+
输出: 6
38+
解释: 给定的三个人分别住在(0,0),(0,4) 和 (2,2):
39+
(0,2) 是一个最佳的碰面点,其总行走距离为 2 + 2 + 2 = 6,最小,因此返回 6
40+
```
41+
42+
- 示例 2:
43+
44+
```python
45+
输入: grid = [[1,1]]
46+
输出: 1
47+
```
48+
49+
## 解题思路
50+
51+
### 思路 1:中位数优化
52+
53+
这是一个经典的数学优化问题。关键观察是:对于曼哈顿距离,$x$ 坐标和 $y$ 坐标可以独立优化。
54+
55+
具体思路:
56+
1. 收集所有朋友的位置坐标,分别得到 $x$ 坐标数组 $X$ 和 $y$ 坐标数组 $Y$
57+
2. 对 $x$ 坐标和 $y$ 坐标分别排序
58+
3. 最优的碰头地点的 $x$ 坐标是 $X$ 的中位数,$y$ 坐标是 $Y$ 的中位数
59+
4. 计算所有朋友到最优碰头地点的曼哈顿距离之和
60+
61+
**数学原理**:对于一维情况,中位数是最小化绝对偏差和的最优解。由于曼哈顿距离可以分解为 $x$ 坐标差和 $y$ 坐标差的和,所以可以分别优化。
62+
63+
### 思路 1:代码
64+
65+
```python
66+
class Solution:
67+
def minTotalDistance(self, grid: List[List[int]]) -> int:
68+
"""
69+
找到最佳的碰头地点,使所有朋友的总行走距离最小
70+
"""
71+
m, n = len(grid), len(grid[0])
72+
73+
# 收集所有朋友的位置坐标
74+
x_coords = []
75+
y_coords = []
76+
77+
for i in range(m):
78+
for j in range(n):
79+
if grid[i][j] == 1:
80+
x_coords.append(i) # 行坐标
81+
y_coords.append(j) # 列坐标
82+
83+
# 对坐标进行排序
84+
x_coords.sort()
85+
y_coords.sort()
86+
87+
# 计算中位数位置
88+
k = len(x_coords)
89+
median_x = x_coords[k // 2] # x 坐标的中位数
90+
median_y = y_coords[k // 2] # y 坐标的中位数
91+
92+
# 计算总距离
93+
total_distance = 0
94+
for i in range(k):
95+
total_distance += abs(x_coords[i] - median_x) + abs(y_coords[i] - median_y)
96+
97+
return total_distance
98+
```
99+
100+
### 思路 1:复杂度分析
101+
102+
- **时间复杂度**:$O(m \times n + k \log k)$,其中 $m \times n$ 是遍历网格的时间,$k$ 是朋友的数量,$k \log k$ 是排序的时间。
103+
- **空间复杂度**:$O(k)$,用于存储所有朋友的坐标。

0 commit comments

Comments
 (0)