英文原文
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: group1 [1,4] and group2 [2,3].
Example 2:
Input: n = 3, dislikes = [[1,2],[1,3],[2,3]] Output: false
Example 3:
Input: n = 5, dislikes = [[1,2],[2,3],[3,4],[4,5],[1,5]] Output: false
Constraints:
1 <= n <= 2000
0 <= dislikes.length <= 104
dislikes[i].length == 2
1 <= dislikes[i][j] <= n
ai < bi
- All the pairs of
dislikes
are unique.
中文题目
给定一组 N
人(编号为 1, 2, ..., N
), 我们想把每个人分进任意大小的两组。
每个人都可能不喜欢其他人,那么他们不应该属于同一组。
形式上,如果 dislikes[i] = [a, b]
,表示不允许将编号为 a
和 b
的人归入同一组。
当可以用这种方法将所有人分进两组时,返回 true
;否则返回 false
。
示例 1:
输入:N = 4, dislikes = [[1,2],[1,3],[2,4]] 输出:true 解释:group1 [1,4], group2 [2,3]
示例 2:
输入:N = 3, dislikes = [[1,2],[1,3],[2,3]] 输出:false
示例 3:
输入:N = 5, dislikes = [[1,2],[2,3],[3,4],[4,5],[1,5]] 输出:false
提示:
1 <= N <= 2000
0 <= dislikes.length <= 10000
dislikes[i].length == 2
1 <= dislikes[i][j] <= N
dislikes[i][0] < dislikes[i][1]
- 对于
dislikes[i] == dislikes[j]
不存在i != j
通过代码
官方题解
方法:深度优先搜索
思路
尝试将每个人分配到一个组是很自然的想法。假设第一组中的人是红色,第二组中的人是蓝色。
如果第一个人是红色的,那么这个人不喜欢的人必须是蓝色的。然后,任何不喜欢蓝色人的人都是红色的,那么任何不喜欢红色人的人都是蓝色的,依此类推。
如果在任何时候存在冲突,那么这个任务是不可能的完成的,因为从第一步开始每一步都符合逻辑。如果没有冲突,那么着色是有效的,所以答案是 true
。
算法
考虑由给定的 “不喜欢” 边缘形成的 N
人的图表。我们要检查这个图的每个连通分支是否为二分的。
对于每个连通的部分,我们只需试着用两种颜色对它进行着色,就可以检查它是否是二分的。如何做到这一点:将任一结点涂成红色,然后将它的所有邻居都涂成蓝色,然后将所有的邻居的邻居都涂成红色,以此类推。如果我们将一个红色结点涂成蓝色(或蓝色结点涂成红色),那么就会产生冲突。
class Solution {
ArrayList<Integer>[] graph;
Map<Integer, Integer> color;
public boolean possibleBipartition(int N, int[][] dislikes) {
graph = new ArrayList[N+1];
for (int i = 1; i <= N; ++i)
graph[i] = new ArrayList();
for (int[] edge: dislikes) {
graph[edge[0]].add(edge[1]);
graph[edge[1]].add(edge[0]);
}
color = new HashMap();
for (int node = 1; node <= N; ++node)
if (!color.containsKey(node) && !dfs(node, 0))
return false;
return true;
}
public boolean dfs(int node, int c) {
if (color.containsKey(node))
return color.get(node) == c;
color.put(node, c);
for (int nei: graph[node])
if (!dfs(nei, c ^ 1))
return false;
return true;
}
}
class Solution(object):
def possibleBipartition(self, N, dislikes):
graph = collections.defaultdict(list)
for u, v in dislikes:
graph[u].append(v)
graph[v].append(u)
color = {}
def dfs(node, c = 0):
if node in color:
return color[node] == c
color[node] = c
return all(dfs(nei, c ^ 1) for nei in graph[node])
return all(dfs(node)
for node in range(1, N+1)
if node not in color)
复杂度分析
时间复杂度:$O(N + E)$,其中 $E$ 是
dislikes
的长度。空间复杂度:$O(N + E)$。
统计信息
通过次数 | 提交次数 | AC比率 |
---|---|---|
9696 | 22280 | 43.5% |
提交历史
提交时间 | 提交结果 | 执行时间 | 内存消耗 | 语言 |
---|