Skip to content

Commit f78749d

Browse files
author
lucifer
committed
feat: $785 $886
1 parent 48714db commit f78749d

File tree

3 files changed

+261
-2
lines changed

3 files changed

+261
-2
lines changed

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -250,21 +250,23 @@ leetcode 题解,记录自己的 leetcode 解题之路。
250250
- [0343.integer-break](./problems/343.integer-break.md)🆕
251251
- [0365.water-and-jug-problem](./problems/365.water-and-jug-problem.md)
252252
- [0378.kth-smallest-element-in-a-sorted-matrix](./problems/378.kth-smallest-element-in-a-sorted-matrix.md)
253-
- [0380.insert-delete-getrandom-o1](./problems/380.insert-delete-getrandom-o1.md)🆕
253+
- [0380.insert-delete-getrandom-o1](./problems/380.insert-delete-getrandom-o1.md)
254254
- [0416.partition-equal-subset-sum](./problems/416.partition-equal-subset-sum.md)🖊
255255
- [0445.add-two-numbers-ii](./problems/445.add-two-numbers-ii.md)
256256
- [0454.4-sum-ii](./problems/454.4-sum-ii.md)
257257
- [0474.ones-and-zeros](./problems/474.ones-and-zeros-en.md)
258258
- [0494.target-sum](./problems/494.target-sum.md)
259259
- [0516.longest-palindromic-subsequence](./problems/516.longest-palindromic-subsequence.md)
260260
- [0518.coin-change-2](./problems/518.coin-change-2.md)
261-
- [0547.friend-circles](./problems/547.friend-circles-en.md) 🆕
261+
- [0547.friend-circles](./problems/547.friend-circles-en.md)
262262
- [0560.subarray-sum-equals-k](./problems/560.subarray-sum-equals-k.md)
263263
- [0609.find-duplicate-file-in-system](./problems/609.find-duplicate-file-in-system.md)
264264
- [0718.maximum-length-of-repeated-subarray](./problems/718.maximum-length-of-repeated-subarray.md)
265+
- [0785.is-graph-bipartite](./problems/785.is-graph-bipartite.md) 🆕
265266
- [0820.short-encoding-of-words](./problems/820.short-encoding-of-words.md) 🖊
266267
- [0875.koko-eating-bananas](./problems/875.koko-eating-bananas.md)
267268
- [0877.stone-game](./problems/877.stone-game.md)
269+
- [0886.possible-bipartition](./problems/886.possible-bipartition.md) 🆕
268270
- [0900.rle-iterator](./problems/900.rle-iterator.md)
269271
- [0912.sort-an-array](./problems/912.sort-an-array.md)
270272
- [0935.knight-dialer](./problems/935.knight-dialer.md) 🆕

problems/785.is-graph-bipartite.md

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
## 题目地址(785. 判断二分图)
2+
3+
https://leetcode-cn.com/problems/is-graph-bipartite/
4+
5+
## 题目描述
6+
7+
```
8+
给定一个无向图 graph,当这个图为二分图时返回 true。
9+
10+
如果我们能将一个图的节点集合分割成两个独立的子集 A 和 B,并使图中的每一条边的两个节点一个来自 A 集合,一个来自 B 集合,我们就将这个图称为二分图。
11+
12+
graph 将会以邻接表方式给出,graph[i]表示图中与节点 i 相连的所有节点。每个节点都是一个在 0 到 graph.length-1 之间的整数。这图中没有自环和平行边: graph[i]  中不存在 i,并且 graph[i]中没有重复的值。
13+
14+
示例 1:
15+
输入: [[1,3], [0,2], [1,3], [0,2]]
16+
输出: true
17+
解释:
18+
无向图如下:
19+
0----1
20+
| |
21+
| |
22+
3----2
23+
我们可以将节点分成两组: {0, 2} 和 {1, 3}。
24+
25+
示例 2:
26+
输入: [[1,2,3], [0,2], [0,1,3], [0,2]]
27+
输出: false
28+
解释:
29+
无向图如下:
30+
0----1
31+
| \ |
32+
| \ |
33+
3----2
34+
我们不能将节点分割成两个独立的子集。
35+
注意:
36+
37+
graph 的长度范围为 [1, 100]。
38+
graph[i] 中的元素的范围为 [0, graph.length - 1]。
39+
graph[i] 不会包含 i 或者有重复的值。
40+
图是无向的: 如果 j 在 graph[i]里边, 那么 i 也会在 graph[j]里边。
41+
```
42+
43+
## 前置知识
44+
45+
- 图的遍历
46+
- DFS
47+
48+
## 思路
49+
50+
和 886 思路一样。 我甚至**直接拿过来 dfs 函数一行代码没改就 AC 了**
51+
52+
唯一需要调整的地方是 graph 。 我将其转换了一下,具体可以看代码,非常简单易懂。
53+
54+
具体算法:
55+
56+
- 设置一个长度为 N 的数组 colors,colors[i] 表示 节点 i 的颜色,0 表示无颜色, 1 表示一种颜色, - 1 表示另一种颜色。
57+
- 初始化 colors 全部为 0
58+
- 构图(这里有邻接矩阵) 使得 grid[i][j] 表示 i 和 j 是否有连接(这里用 0 表示无, 1 表示有)
59+
- 遍历图。
60+
- 如果当前节点未染色,则染色,不妨染为颜色 1
61+
- 递归遍历其邻居
62+
- 如果邻居没有染色, 则染为另一种颜色。即 color \* - 1,其中 color 为当前节点的颜色
63+
- 否则,判断当前节点和邻居的颜色是否一致,不一致则返回 False,否则返回 True
64+
65+
强烈建议两道题一起练习一下。
66+
67+
## 关键点
68+
69+
- 图的建立和遍历
70+
- colors 数组
71+
72+
## 代码
73+
74+
```py
75+
class Solution:
76+
def dfs(self, grid, colors, i, color, N):
77+
colors[i] = color
78+
for j in range(N):
79+
if grid[i][j] == 1:
80+
if colors[j] == color:
81+
return False
82+
if colors[j] == 0 and not self.dfs(grid, colors, j, -1 * color, N):
83+
return False
84+
return True
85+
86+
def isBipartite(self, graph: List[List[int]]) -> bool:
87+
N = len(graph)
88+
grid = [[0] * N for _ in range(N)]
89+
colors = [0] * N
90+
for i in range(N):
91+
for j in graph[i]:
92+
grid[i][j] = 1
93+
for i in range(N):
94+
if colors[i] == 0 and not self.dfs(grid, colors, i, 1, N):
95+
return False
96+
return True
97+
```
98+
99+
**复杂度分析**
100+
101+
- 时间复杂度:$O(N^2)$
102+
- 空间复杂度:$O(N)$
103+
104+
## 相关问题
105+
106+
- [886. 可能的二分法](./886.possible-bipartition.md)
107+
108+
更多题解可以访问我的 LeetCode 题解仓库:https://github.com/azl397985856/leetcode 。 目前已经 30K star 啦。
109+
110+
关注公众号力扣加加,努力用清晰直白的语言还原解题思路,并且有大量图解,手把手教你识别套路,高效刷题。

problems/886.possible-bipartition.md

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
## 题目地址(886. 可能的二分法)
2+
3+
https://leetcode-cn.com/problems/is-graph-bipartite/
4+
5+
## 题目描述
6+
7+
```
8+
给定一组 N 人(编号为 1, 2, ..., N), 我们想把每个人分进任意大小的两组。
9+
10+
每个人都可能不喜欢其他人,那么他们不应该属于同一组。
11+
12+
形式上,如果 dislikes[i] = [a, b],表示不允许将编号为 a 和 b 的人归入同一组。
13+
14+
当可以用这种方法将每个人分进两组时,返回 true;否则返回 false。
15+
16+
 
17+
18+
示例 1:
19+
20+
输入:N = 4, dislikes = [[1,2],[1,3],[2,4]]
21+
输出:true
22+
解释:group1 [1,4], group2 [2,3]
23+
示例 2:
24+
25+
输入:N = 3, dislikes = [[1,2],[1,3],[2,3]]
26+
输出:false
27+
示例 3:
28+
29+
输入:N = 5, dislikes = [[1,2],[2,3],[3,4],[4,5],[1,5]]
30+
输出:false
31+
 
32+
33+
提示:
34+
35+
1 <= N <= 2000
36+
0 <= dislikes.length <= 10000
37+
dislikes[i].length == 2
38+
1 <= dislikes[i][j] <= N
39+
dislikes[i][0] < dislikes[i][1]
40+
对于dislikes[i] == dislikes[j] 不存在 i != j
41+
42+
```
43+
44+
## 前置知识
45+
46+
- 图的遍历
47+
- DFS
48+
49+
## 思路
50+
51+
这是一个图的问题。解决这种问题一般是要遍历图才行的,这也是图的套路。 那么遍历的话,你要有一个合适的数据结构。 比较常见的图存储方式是邻接矩阵和邻接表。
52+
53+
而我们这里为了操作方便(代码量),直接使用邻接矩阵。由于是互相不喜欢,不存在一个喜欢另一个,另一个不喜欢一个的情况,因此这是无向图。而无向图邻接矩阵实际上是会浪费空间,具体看我下方画的图。
54+
55+
而题目给我们的二维矩阵并不是现成的邻接矩阵形式,因此我们需要自己生成。
56+
57+
我们用 1 表示互相不喜欢(dislike each other)。
58+
59+
```py
60+
graph = [[0] * N for i in range(N)]
61+
for a, b in dislikes:
62+
graph[a - 1][b - 1] = 1
63+
graph[b - 1][a - 1] = 1
64+
```
65+
66+
![image.png](https://pic.leetcode-cn.com/21985e69144ba1fef518085d5bdc8e0f6d363a33ddef3938523603871466eace-image.png)
67+
68+
同时可以用 hashmap 或者数组存储 N 个人的分组情况, 业界关于这种算法一般叫染色法,因此我们命名为 colors,其实对应的本题叫 groups 更合适。
69+
70+
![image.png](https://pic.leetcode-cn.com/ebd70e4bdeb3fbcc7fe3cdd70f5679db0cec60c4f18ab077a6c9844d58c79776-image.png)
71+
72+
我们用:
73+
74+
- 0 表示没有分组
75+
- 1 表示分组 1
76+
- -1 表示分组 2
77+
78+
之所以用 0,1,-1,而不是 0,1,2 是因为我们会在不能分配某一组的时候尝试分另外一组,这个时候有其中一组转变为另外一组就可以直接乘以-1,而 0,1,2 这种就稍微麻烦一点而已。
79+
80+
具体算法:
81+
82+
- 遍历每一个人,尝试给他们进行分组,比如默认分配组 1.
83+
84+
![image.png](https://pic.leetcode-cn.com/a6a691a28d74245501ebd543d382fa277a7825b8ceb82d4c7adb2ecdc5834793-image.png)
85+
86+
- 然后遍历这个人讨厌的人,尝试给他们分另外一组,如果不可以分配另外一组,则返回 False
87+
88+
那问题的关键在于如何判断“不可以分配另外一组”呢?
89+
90+
![image.png](https://pic.leetcode-cn.com/fe52fe6cd9cb3a8e3c6702b121be858c182d5bba64de89a94eb17352eff6bbea-image.png)
91+
92+
实际上,我们已经用 colors 记录了分组信息,对于每一个人如果分组确定了,我们就更新 colors,那么对于一个人如果分配了一个组,并且他讨厌的人也被分组之后,**分配的组和它只能是一组**,那么“就是不可以分配另外一组”。
93+
94+
代码表示就是:
95+
96+
```py
97+
# 其中j 表示当前是第几个人,N表示总人数。 dfs的功能就是根据colors和graph分配组,true表示可以分,false表示不可以,具体代码见代码区。
98+
if colors[j] == 0 and not self.dfs(graph, colors, j, -1 * color, N)
99+
```
100+
101+
## 关键点
102+
103+
- 二分图
104+
- 染色法
105+
- 图的建立和遍历
106+
- colors 数组
107+
108+
## 代码
109+
110+
```py
111+
class Solution:
112+
def dfs(self, graph, colors, i, color, N):
113+
colors[i] = color
114+
for j in range(N):
115+
# dislike eachother
116+
if graph[i][j] == 1:
117+
if colors[j] == color:
118+
return False
119+
if colors[j] == 0 and not self.dfs(graph, colors, j, -1 * color, N):
120+
return False
121+
return True
122+
123+
def possibleBipartition(self, N: int, dislikes: List[List[int]]) -> bool:
124+
graph = [[0] * N for i in range(N)]
125+
colors = [0] * N
126+
for a, b in dislikes:
127+
graph[a - 1][b - 1] = 1
128+
graph[b - 1][a - 1] = 1
129+
for i in range(N):
130+
if colors[i] == 0 and not self.dfs(graph, colors, i, 1, N):
131+
return False
132+
return True
133+
134+
```
135+
136+
**复杂度分析**
137+
138+
- 时间复杂度:$O(N^2)$
139+
- 空间复杂度:$O(N)$
140+
141+
## 相关问题
142+
143+
- [785. 判断二分图](785.is-graph-bipartite.md)
144+
145+
更多题解可以访问我的 LeetCode 题解仓库:https://github.com/azl397985856/leetcode 。 目前已经 30K star 啦。
146+
147+
关注公众号力扣加加,努力用清晰直白的语言还原解题思路,并且有大量图解,手把手教你识别套路,高效刷题。

0 commit comments

Comments
 (0)