Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Transform LeetCode 101 into an Interactive Multi-Language Docusaurus Site #95

Open
wants to merge 48 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
09b85fb
scaffolding
noworneverev Nov 11, 2024
3d57f39
add github action
noworneverev Nov 11, 2024
891e46b
fix config
noworneverev Nov 11, 2024
419e0f6
correct branch name
noworneverev Nov 11, 2024
9db658b
chapter 1 - 3
noworneverev Nov 12, 2024
c0bdc6c
chapter 4
noworneverev Nov 13, 2024
2e83571
chapter 5
noworneverev Nov 13, 2024
815f79f
add cover pic
noworneverev Nov 13, 2024
0e13c07
chapter 6
noworneverev Nov 13, 2024
164146f
chapter 7
noworneverev Nov 14, 2024
cf8afe5
chapter 8
noworneverev Nov 14, 2024
3f24539
chapter 9
noworneverev Nov 14, 2024
5e8cf7a
chapter 10
noworneverev Nov 14, 2024
fa80896
chapter 11
noworneverev Nov 14, 2024
a0b1e28
chapter 12
noworneverev Nov 14, 2024
4d9b966
chapter 13
noworneverev Nov 14, 2024
8228f23
chapter 14
noworneverev Nov 14, 2024
9cfe50e
chapter 15
noworneverev Nov 14, 2024
efde52e
acknowledgments
noworneverev Nov 14, 2024
7fe259f
i18n chapter 1 - 5
noworneverev Nov 15, 2024
b6decad
i18n chapter 6
noworneverev Nov 22, 2024
01074a0
i18n chapter 7
noworneverev Nov 24, 2024
43940ac
i18n chapter 8
noworneverev Nov 24, 2024
847370d
fix i18n bug
noworneverev Nov 24, 2024
c3181fb
i18n chapter 9
noworneverev Nov 25, 2024
f2375cb
chapter 1 exercise solutions
noworneverev Nov 26, 2024
f5001db
i18n chapter 10
noworneverev Nov 26, 2024
d7e0437
add separators
noworneverev Nov 26, 2024
8557774
i18n preface
noworneverev Nov 27, 2024
b78413b
i18n acknowledgments
noworneverev Nov 27, 2024
702ea47
i18n chapter 11
noworneverev Nov 27, 2024
a8443e4
i18n chapter 12
noworneverev Nov 27, 2024
0aea056
i18n chapter 13
noworneverev Nov 27, 2024
e36ad55
i18n chapter 14
noworneverev Nov 27, 2024
faa23b1
i18n chapter 15
noworneverev Nov 27, 2024
f423731
add logo
noworneverev Nov 27, 2024
8a42520
add local search
noworneverev Nov 27, 2024
4f00ac6
fix local search
noworneverev Nov 27, 2024
cab36d9
fix i18n and footer
noworneverev Nov 27, 2024
ed61768
Merge branch 'changgyhub:master' into master
noworneverev Nov 27, 2024
21a77bd
chapter 2 complexity analysis
noworneverev Nov 29, 2024
300777a
Ch2 exercise solutions
noworneverev Nov 29, 2024
8daf2f8
Ch3 complexity analysis
noworneverev Nov 30, 2024
67b0833
Upgrade Docusaurus packages
noworneverev Dec 1, 2024
7fc5f43
Ch3 exercise solutions
noworneverev Dec 1, 2024
30473b3
Fix i18n zh-TW
noworneverev Dec 1, 2024
0e494f4
Ch4 complexity analysis
noworneverev Dec 9, 2024
3de5d5e
Ch4 exercise solutions
noworneverev Dec 9, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
chapter 14
noworneverev committed Nov 14, 2024
commit 8228f23419b104ace4a20ff8aa961de501f548fb

This file was deleted.

16 changes: 16 additions & 0 deletions leetcode_101/docs/14-graphs/14-1-data-structure-introduction.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
sidebar_position: 75
---

# 14.1 数据结构介绍

作为指针三剑客之三,图是树的升级版。``通常分为有向(directed)或无向(undirected),有循环(cyclic)或无循环(acyclic),所有节点相连(connected)或不相连(disconnected)。树即是一个相连的无向无环图,而另一种很常见的图是`有向无环图`(Directed Acyclic Graph,DAG)。

<figure>
<span style={{ display: 'block', width: '20%', margin: '0 auto' }}>
![](14.1.png)
</span>
<figcaption style={{ textAlign: 'center' }}>图 14.1: 有向无环图样例</figcaption>
</figure>

图通常有两种表示方法。假设图中一共有 n 个节点、m 条边。第一种表示方法是`邻接矩阵`(adjacency matrix):我们可以建立一个 n × n 的矩阵 G,如果第 i 个节点连向第 j 个节点,则 G[i][j] = 1,反之为 0;如果图是无向的,则这个矩阵一定是对称矩阵,即 G[i][j] = G[j][i]。第二种表示方法是`邻接链表`(adjacency list):我们可以建立一个大小为 n 的数组,每个位置 i 储存一个数组或者链表,表示第 i 个节点连向的其它节点。邻接矩阵空间开销比邻接链表大,但是邻接链表不支持快速查找 i 和 j 是否相连,因此两种表示方法可以根据题目需要适当选择。除此之外,我们也可以直接用一个 m × 2 的矩阵储存所有的边。
5 changes: 0 additions & 5 deletions leetcode_101/docs/14-graphs/14-2-bipartite-graph.md

This file was deleted.

90 changes: 90 additions & 0 deletions leetcode_101/docs/14-graphs/14-2-bipartite-graph.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
---
sidebar_position: 76
---

# 14.2 二分图

`二分图`算法也称为`染色法`,是一种广度优先搜索。如果可以用两种颜色对图中的节点进行着色,并且保证相邻的节点颜色不同,那么图为二分。

## [785. Is Graph Bipartite?](https://leetcode.com/problems/is-graph-bipartite/)

### 题目描述

给定一个图,判断其是否可以二分。

### 输入输出样例

输入是邻接链表表示的图(如位置 0 的邻接链表为 [1,3],表示 0 与 1、0 与 3 相连);输出是一个布尔值,表示图是否二分。

```
Input: [[1,3], [0,2], [1,3], [0,2]]
0----1
| |
| |
3----2
Output: true
```

在这个样例中,我们可以把 {0,2} 分为一组,把 {1,3} 分为另一组。

### 题解

利用队列和广度优先搜索,我们可以对未染色的节点进行染色,并且检查是否有颜色相同的相邻节点存在。注意在代码中,我们用 0 表示未检查的节点,用 1 和 2 表示两种不同的颜色。

<Tabs>
<TabItem value="cpp" label="C++">

```cpp
bool isBipartite(vector<vector<int>>& graph) {
int n = graph.size();
vector<int> color(n, 0);
queue<int> q;
for (int i = 0; i < n; ++i) {
if (color[i] == 0) {
q.push(i);
color[i] = 1;
}
while (!q.empty()) {
int node = q.front();
q.pop();
for (int j : graph[node]) {
if (color[j] == 0) {
q.push(j);
color[j] = color[node] == 2 ? 1 : 2;
} else if (color[j] == color[node]) {
return false;
}
}
}
}
return true;
}
```

</TabItem>
<TabItem value="py" label="Python">

```py
def isBipartite(graph: List[List[int]]) -> bool:
n = len(graph)
color = [0] * n
q = collections.deque()

for i in range(n):
if color[i] == 0:
q.append(i)
color[i] = 1
while len(q) > 0:
node = q.popleft()
for j in graph[node]:
if color[j] == 0:
q.append(j)
color[j] = 1 if color[node] == 2 else 2
elif color[j] == color[node]:
return False
return True
```

</TabItem>

</Tabs>
5 changes: 0 additions & 5 deletions leetcode_101/docs/14-graphs/14-3-topological-sorting.md

This file was deleted.

97 changes: 97 additions & 0 deletions leetcode_101/docs/14-graphs/14-3-topological-sorting.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
---
sidebar_position: 77
---

# 14.3 拓扑排序

`拓扑排序`(topological sort)是一种常见的,对有向无环图排序的算法。给定有向无环图中的 $N$ 个节点,我们把它们排序成一个线性序列;若原图中节点 i 指向节点 j,则排序结果中 i 一定在 j 之前。拓扑排序的结果不是唯一的,只要满足以上条件即可。

## [210. Course Schedule II](https://leetcode.com/problems/course-schedule-ii/)

### 题目描述

给定 N 个课程和这些课程的前置必修课,求可以一次性上完所有课的顺序。

### 输入输出样例

输入是一个正整数,表示课程数量,和一个二维矩阵,表示所有的有向边(如 [1,0] 表示上课程 1 之前必须先上课程 0)。输出是一个一维数组,表示拓扑排序结果。

```
Input: numCourses = 4, prerequisites = [[1,0],[2,0],[3,1],[3,2]]
Output: [0,1,2,3]
```

在这个样例中,另一种可行的顺序是 [0,2,1,3]

### 题解

我们可以先建立一个邻接矩阵表示图,方便进行直接查找。这里注意我们将所有的边反向,使得如果课程 i 指向课程 j,那么课程 i 需要在课程 j 前面先修完。这样更符合我们的直观理解。

拓扑排序也可以被看成是广度优先搜索的一种情况:我们先遍历一遍所有节点,把入度为 0 的节点(即没有前置课程要求)放在队列中。在每次从队列中获得节点时,我们将该节点放在目前排序的末尾,并且把它指向的课程的入度各减 1;如果在这个过程中有课程的所有前置必修课都已修完(即入度为 0),我们把这个节点加入队列中。当队列的节点都被处理完时,说明所有的节点都已排好序,或因图中存在循环而无法上完所有课程。

<Tabs>
<TabItem value="cpp" label="C++">

```cpp
vector<int> findOrder(int numCourses, vector<vector<int>>& prerequisites) {
vector<vector<int>> graph(numCourses, vector<int>());
vector<int> indegree(numCourses, 0), schedule;
for (const auto& pr : prerequisites) {
graph[pr[1]].push_back(pr[0]);
++indegree[pr[0]];
}
queue<int> q;
for (int i = 0; i < indegree.size(); ++i) {
if (indegree[i] == 0) {
q.push(i);
}
}
while (!q.empty()) {
int u = q.front();
q.pop();
schedule.push_back(u);
for (int v : graph[u]) {
--indegree[v];
if (indegree[v] == 0) {
q.push(v);
}
}
}
for (int i = 0; i < indegree.size(); ++i) {
if (indegree[i] != 0) {
return vector<int>();
}
}
return schedule;
}
```

</TabItem>
<TabItem value="py" label="Python">

```py
def findOrder(numCourses: int, prerequisites: List[List[int]]) -> List[int]:
graph = [[] for _ in range(numCourses)]
indegree = [0] * numCourses
schedule = []

for pr_from, pr_to in prerequisites:
graph[pr_to].append(pr_from)
indegree[pr_from] += 1

q = collections.deque([i for i, deg in enumerate(indegree) if deg == 0])

while len(q) > 0:
u = q.popleft()
schedule.append(u)
for v in graph[u]:
indegree[v] -= 1
if indegree[v] == 0:
q.append(v)

return schedule if all(deg == 0 for deg in indegree) else []
```
</TabItem>
</Tabs>
16 changes: 16 additions & 0 deletions leetcode_101/docs/14-graphs/14-4-exercises.md
Original file line number Diff line number Diff line change
@@ -3,3 +3,19 @@ sidebar_position: 78
---

# 14.4 练习

## 基础难度

### [1059. All Paths from Source Lead to Destination](https://leetcode.com/problems/all-paths-from-source-lead-to-destination/)

虽然使用深度优先搜索可以解决大部分的图遍历问题,但是注意判断是否陷入了环路。

## 进阶难度

### [1135. Connecting Cities With Minimum Cost](https://leetcode.com/problems/connecting-cities-with-minimum-cost/)

笔者其实已经把这道题的题解写好了,才发现这道题是需要解锁才可以看的题目。为了避免版权纠纷,故将其移至练习题内。本题考察最小生成树(minimum spanning tree, MST)的求法,通常可以用两种方式求得:Prim’s Algorithm,利用优先队列选择最小的消耗;以及 Kruskal’s Algorithm,排序后使用并查集。

### [882. Reachable Nodes In Subdivided Graph](https://leetcode.com/problems/reachable-nodes-in-subdivided-graph/)

这道题笔者考虑了很久,最终决定把它放在练习题而非详细讲解。本题是经典的节点最短距离问题,常用的算法有 Bellman-Ford 单源最短路算法,以及 Dijkstra 无负边单源最短路算法。虽然经典,但是 LeetCode 很少有相关的题型,因此这里仅供读者自行深入学习。
Binary file added leetcode_101/docs/14-graphs/14.1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion leetcode_101/docs/14-graphs/_category_.json
Original file line number Diff line number Diff line change
@@ -3,6 +3,6 @@
"position": 14,
"link": {
"type": "generated-index",
"description": "5 minutes to learn the most important Docusaurus concepts."
"description": "第 14 章 指针三剑客之三:图"
}
}