Skip to content

Commit 1e20413

Browse files
committed
1 parent ac8143e commit 1e20413

File tree

1 file changed

+364
-0
lines changed

1 file changed

+364
-0
lines changed

Diff for: leetcode算法之图.md

+364
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,364 @@
1+
今天来盘一盘 **** 这类题目
2+
3+
这类题目对我来说也是比较难的,比较难搞。
4+
5+
```
6+
有向无环图的拓扑排序(BFS, DFS)
7+
8+
利用并查集处理连通域问题
9+
```
10+
11+
使用**python**刷题分类整理的笔记,请参考: [https://github.com/lxztju/leetcode-algorithm/tree/v1](https://github.com/lxztju/leetcode-algorithm/tree/v1)
12+
13+
##
14+
15+
### BFS与DFS
16+
17+
* 785 判断二分图 (Medium)
18+
* 207 课程表 (Medium)
19+
* 210 课程表 II (Medium)
20+
21+
### 并查集
22+
23+
并查集是一种树型的数据结构,主要用于处理连通域的问题,用于处理一些不交集的合并及查询问题。主要的操作有如下的步骤:
24+
25+
Find:确定元素属于哪一个子集。它可以被用来确定两个元素是否属于同一子集。
26+
Union:将两个子集合并成同一个集合。
27+
28+
* 684 冗余连接 (Medium)
29+
30+
31+
### BFS与DFS
32+
33+
34+
35+
#### 785 判断二分图 (Medium)
36+
使用染色法,0代表一种颜色,1代表另外一种颜色, -1表示未染色,相邻的元素不能染成同样的颜色。
37+
38+
* DFS
39+
40+
```c++
41+
class Solution {
42+
public:
43+
bool isBipartite(vector<vector<int>>& graph) {
44+
int n = graph.size();
45+
vector<int> colors(n, -1);
46+
for (int i = 0; i< n; i++){
47+
if (colors[i] == -1){
48+
if (!dfs(graph, colors, i, 0))
49+
return false;
50+
}
51+
}
52+
return true;
53+
}
54+
55+
bool dfs(vector<vector<int>>& graph, vector<int>& colors, int index, int c){
56+
57+
colors[index] = c;
58+
for (int i = 0; i < graph[index].size(); i++){
59+
int node = graph[index][i];
60+
if (colors[node] != -1){
61+
if (colors[node] == c) return false;
62+
else continue;
63+
}
64+
else
65+
if ( ! dfs(graph, colors, node, 1-c))
66+
return false;
67+
}
68+
return true;
69+
}
70+
};
71+
```
72+
73+
* BFS
74+
75+
```c++
76+
class Solution {
77+
public:
78+
bool isBipartite(vector<vector<int>>& graph) {
79+
int n = graph.size();
80+
vector<int> colors(n, -1);
81+
queue<pair<int, int>> q;
82+
for (int i = 0; i<n; i++){
83+
if ( colors[i] != -1) continue;
84+
q.push(make_pair(i, 0));
85+
while (! q.empty()){
86+
auto nodeLevel = q.front();
87+
int node = nodeLevel.first;
88+
int level = nodeLevel.second;
89+
q.pop();
90+
if (level % 2 == 0){
91+
if (colors[node] == 1)
92+
return false;
93+
colors[node] = 0;
94+
}
95+
else{
96+
if (colors[node] == 0)
97+
return false;
98+
colors[node] = 1;
99+
}
100+
for (auto node1 : graph[node]){
101+
if (colors[node1] == -1)
102+
q.push(make_pair(node1, level+1));
103+
}
104+
}
105+
}
106+
return true;
107+
}
108+
};
109+
```
110+
111+
112+
#### 207 课程表 (Medium)
113+
114+
* DFS
115+
116+
```c++
117+
class Solution {
118+
public:
119+
bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
120+
// 不能有环, dfs
121+
vector<int> visited(numCourses, -1); // -1表示没有访问过, 0表示被其他节点访问过,1表示被本节点访问过
122+
vector<vector<int>> edges(numCourses, vector<int>());
123+
124+
// 构建邻接表
125+
for (int i = 0; i < prerequisites.size(); i++){
126+
int start = prerequisites[i][1];
127+
int end = prerequisites[i][0];
128+
// cout<<start<<" "<<end<<endl;
129+
edges[start].push_back(end);
130+
}
131+
132+
for( int i = 0; i < numCourses; i++){
133+
if (visited[i] != -1) continue;
134+
if (! dfs(edges, visited, i))
135+
return false;
136+
}
137+
return true;
138+
}
139+
140+
bool dfs(vector<vector<int>>& edges, vector<int>& visited,int index){
141+
142+
if (visited[index] == 1) return false;
143+
if (visited[index] == 0) return true;
144+
visited[index] = 1;
145+
for (auto node : edges[index]){
146+
if (! dfs(edges, visited, node))
147+
return false;
148+
}
149+
visited[index] = 0;
150+
return true;
151+
}
152+
};
153+
```
154+
155+
156+
* BFS(入度表)
157+
158+
159+
```c++
160+
/*
161+
1. 转换为邻接表并生成入度表
162+
2. 将入度为0的节点入队。
163+
3. 遍历整个队列,如果队列不为空,将队首出列,并将邻接节点的入度减一,将入度为0的节点重新入度。
164+
*/
165+
class Solution {
166+
public:
167+
bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
168+
// 不能有环, dfs
169+
vector<int> indegrees(numCourses, 0);
170+
vector<vector<int>> edges(numCourses, vector<int>());
171+
172+
// 构建邻接表与入度表
173+
for (int i = 0; i < prerequisites.size(); i++){
174+
int start = prerequisites[i][1];
175+
int end = prerequisites[i][0];
176+
edges[start].push_back(end);
177+
indegrees[end]++;
178+
}
179+
queue<int> q;
180+
// 将入度为0的节点入队
181+
for (int i = 0; i < numCourses; i++){
182+
if (indegrees[i] == 0)
183+
q.push(i);
184+
}
185+
while (!q.empty()){
186+
int node = q.front();
187+
q.pop();
188+
// 将邻接的节点入度数减一,并将入度为0的节点入队
189+
for (auto j : edges[node]){
190+
indegrees[j]--;
191+
if (indegrees[j] == 0)
192+
q.push(j);
193+
}
194+
}
195+
// 如果有的节点入度数不为0,那么说明存在环
196+
for (auto i: indegrees){
197+
if (i != 0) return false;
198+
}
199+
return true;
200+
}
201+
};
202+
```
203+
204+
205+
206+
207+
#### 210 课程表 II (Medium)
208+
209+
* DFS
210+
211+
```c++
212+
213+
class Solution {
214+
public:
215+
vector<int> findOrder(int numCourses, vector<vector<int>>& prerequisites) {
216+
vector<vector<int>> edges(numCourses, vector<int>());
217+
for (int i= 0; i < prerequisites.size(); i++){
218+
int start = prerequisites[i][1];
219+
int end = prerequisites[i][0];
220+
edges[start].push_back(end);
221+
}
222+
223+
// for(auto p: edges){
224+
// for (auto v:p)
225+
// cout<<v<<" ";
226+
// cout<<endl;
227+
// }
228+
229+
vector<int> visited(numCourses, -1); // -1表示没有访问过, 0表示被其他节点访问过,1表示被本节点访问过
230+
vector<int> res;
231+
for( int i = 0; i < numCourses; i++){
232+
if (visited[i] != -1) continue;
233+
if (! dfs(edges, visited, res, i))
234+
return {};
235+
}
236+
reverse(res.begin(), res.end());
237+
return res;
238+
}
239+
240+
bool dfs(vector<vector<int>>& edges, vector<int>& visited, vector<int>& res, int index){
241+
242+
if (visited[index] == 1) return false;
243+
if (visited[index] == 0) return true;
244+
visited[index] = 1;
245+
for (auto node : edges[index]){
246+
if (!dfs(edges, visited, res, node))
247+
return false;
248+
}
249+
res.push_back(index);
250+
visited[index] = 0;
251+
return true;
252+
}
253+
};
254+
```
255+
256+
* BFS
257+
258+
```c++
259+
class Solution {
260+
public:
261+
vector<int> findOrder(int numCourses, vector<vector<int>>& prerequisites) {
262+
vector<vector<int>> edges(numCourses, vector<int>());
263+
vector<int> indegress(numCourses, 0);
264+
// 构建邻接表,入度表
265+
for (int i= 0; i < prerequisites.size(); i++){
266+
int start = prerequisites[i][1];
267+
int end = prerequisites[i][0];
268+
edges[start].push_back(end);
269+
indegress[end]++;
270+
}
271+
272+
queue<int> q;
273+
vector<int> res;
274+
// 将入度为0的节点入队
275+
for (int i = 0; i < numCourses; i++){
276+
if (indegress[i] == 0)
277+
q.push(i);
278+
}
279+
// 遍历队列
280+
while (!q.empty()){
281+
int node = q.front();
282+
res.push_back(node);
283+
q.pop();
284+
// 将邻接节点的入度数减一,并将入度为0的节点入队。
285+
for (auto i : edges[node]){
286+
indegress[i]--;
287+
if (indegress[i] == 0)
288+
q.push(i);
289+
}
290+
}
291+
// 如果存在入度不为0的节点,说明存在一个环
292+
for (auto i: indegress){
293+
if ( i != 0)
294+
return {};
295+
}
296+
return res;
297+
}
298+
};
299+
```
300+
301+
302+
### 并查集
303+
304+
#### 684 冗余连接 (Medium)
305+
经典的并查集的套路代码。
306+
307+
```c++
308+
class Solution {
309+
public:
310+
int find(vector<int>&parent, int index){
311+
// 查找一个给定节点的父亲节点。递归的操作。
312+
if (parent[index] != index)
313+
parent[index] = find(parent, parent[index]);
314+
return parent[index];
315+
}
316+
317+
void Union(vector<int>& parent, int index1, int index2){
318+
// index2的父亲节点转换为index1与index2共同的父亲节点。
319+
parent[find(parent,index1)] = find(parent,index2);
320+
}
321+
322+
vector<int> findRedundantConnection(vector<vector<int>>& edges) {
323+
int n = edges.size();
324+
vector<int> parent(n+1, 0);
325+
// 初始化的情况下,每个节点的父亲节点都是自身
326+
for (int i = 1; i< n+1; i++){
327+
parent[i] = i;
328+
}
329+
330+
for (auto edge: edges){
331+
int node1 = edge[0], node2 = edge[1];
332+
// 对于两个节点,如果其父亲节点不一样就融合这两个节点
333+
if (find(parent, node1) != find(parent, node2))
334+
Union(parent, node1, node2);
335+
else
336+
return edge;
337+
}
338+
return {};
339+
}
340+
};
341+
342+
```
343+
344+
345+
346+
347+
348+
349+
350+
351+
352+
353+
354+
## 更多分类刷题资料
355+
356+
* 微信公众号: 小哲AI
357+
358+
![wechat_QRcode](https://img-blog.csdnimg.cn/20210104185413204.jpg)
359+
360+
* GitHub地址: [https://github.com/lxztju/leetcode-algorithm](https://github.com/lxztju/leetcode-algorithm)
361+
* csdn博客: [https://blog.csdn.net/lxztju](https://blog.csdn.net/lxztju)
362+
* 知乎专栏: [https://www.zhihu.com/column/c_1101089619118026752](https://www.zhihu.com/column/c_1101089619118026752)
363+
* AI研习社专栏:[https://www.yanxishe.com/column/109](https://www.yanxishe.com/column/109)
364+

0 commit comments

Comments
 (0)