[LeetCode] 886. Possible Bipartition

We want to split a group of n people (labeled from 1 to n) into two groups of any size. Each person may dislike some other people, and they should not go into the same group.

Given the integer n and the array dislikes where dislikes[i] = [ai, bi] indicates that the person labeled ai does not like the person labeled bi, return true if it is possible to split everyone into two groups in this way.

Example 1:
Input: n = 4, dislikes = [[1,2],[1,3],[2,4]]
Output: true
Explanation: The first group has [1,4], and the second group has [2,3].

Example 2:
Input: n = 3, dislikes = [[1,2],[1,3],[2,3]]
Output: false
Explanation: We need at least 3 groups to divide them. We cannot put them in two groups.

Constraints:
1 <= n <= 2000
0 <= dislikes.length <= 104
dislikes[i].length == 2
1 <= ai < bi <= n
All the pairs of dislikes are unique.

可能的二分法。

给定一组 n 人(编号为 1, 2, ..., n), 我们想把每个人分进任意大小的两组。每个人都可能不喜欢其他人,那么他们不应该属于同一组。

给定整数 n 和数组 dislikes ,其中 dislikes[i] = [ai, bi] ,表示不允许将编号为 ai 和 bi的人归入同一组。当可以用这种方法将所有人分进两组时,返回 true;否则返回 false。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/possible-bipartition
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

题意是给一个数字 n 代表有 n 个人,还有一个二维数组 dislikes,代表每两个人之间的 dislike 关系。请返回是否有可能将 n 个人分成两组。

这个题实际是在考能否将一个图的所有节点分成两组。思路还是染色法,类似 785 题。

复杂度

时间O(V + E) - V是节点数,E是边数
空间O(n)

代码

BFS 实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
class Solution {
public boolean possibleBipartition(int n, int[][] dislikes) {
List<List<Integer>> g = new ArrayList<>();
for (int i = 0; i <= n; i++) {
g.add(new ArrayList<>());
}

for (int[] d : dislikes) {
g.get(d[0]).add(d[1]);
g.get(d[1]).add(d[0]);
}

int[] colors = new int[n + 1];
for (int i = 0; i <= n; i++) {
if (colors[i] != 0) {
continue;
}
Queue<Integer> queue = new LinkedList<>();
queue.offer(i);
colors[i] = 1;
while (!queue.isEmpty()) {
int cur = queue.poll();
for (int nei : g.get(cur)) {
if (colors[nei] == 0) {
colors[nei] = -colors[cur];
queue.offer(nei);
} else if (colors[nei] == colors[cur]) {
return false;
}
}
}
}
return true;
}
}

DFS 实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
class Solution {
public boolean possibleBipartition(int n, int[][] dislikes) {
// corner case
if (dislikes == null || dislikes.length == 0) {
return true;
}

// normal case
List<List<Integer>> graph = new ArrayList<>();
buildGraph(n, dislikes, graph);
int[] colors = new int[n + 1];
for (int i = 0; i < n; i++) {
if (colors[i] == 0 && !dfs(i, graph, colors, 1)) {
return false;
}
}
return true;
}

private void buildGraph(int n, int[][] dislikes, List<List<Integer>> graph) {
for (int i = 0; i <= n; i++) {
graph.add(new ArrayList<>());
}
for (int[] d : dislikes) {
graph.get(d[0]).add(d[1]);
graph.get(d[1]).add(d[0]);
}
}

private boolean dfs(int cur, List<List<Integer>> graph, int[] colors, int color) {
colors[cur] = color;
for (int next : graph.get(cur)) {
// 如果发现某个邻居的颜色和自己一样,则返回false
if (colors[next] == color) {
return false;
}
// 若发现next遍历后会发现某两个邻居染色一样,也返回false
if (colors[next] == 0 && !dfs(next, graph, colors, -color)) {
return false;
}
}
return true;
}
}

相关题目

1
2
3
785. Is Graph Bipartite
886. Possible Bipartition
1129. Shortest Path with Alternating Colors

[LeetCode] 886. Possible Bipartition
https://shurui91.github.io/posts/1466336335.html
Author
Aaron Liu
Posted on
May 28, 2020
Licensed under