一、题目描述
给定一组 n
人(编号为 1, 2, ..., n
), 我们想把每个人分进任意大小的两组。每个人都可能不喜欢其他人,那么他们不应该属于同一组。
给定整数 n
和数组 dislikes
,其中 dislikes[i] = [ai, bi]
,表示不允许将编号为 ai
和 bi
的人归入同一组。当可以用这种方法将所有人分进两组时,返回 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 <= 104
dislikes[i].length == 2
1 <= dislikes[i][j] <= n
ai < bi
dislikes
中每一组都 不同
二、实现
使用并查集解答
type UnionFind struct {
parent []int
}
func newUnionFind(size int) UnionFind {
uf := UnionFind{
parent: make([]int, size),
}
for i := range uf.parent {
uf.parent[i] = i
}
return uf
}
func (uf *UnionFind) Find(x int) int {
if uf.parent[x] != x {
uf.parent[x] = uf.Find(uf.parent[x])
}
return uf.parent[x]
}
func (uf *UnionFind) Union(x, y int) {
rootx := uf.Find(x)
rooty := uf.Find(y)
if rootx == rooty {
return
}
if rootx < rooty {
uf.parent[rooty] = rootx
} else {
uf.parent[rootx] = rooty
}
}
func (uf *UnionFind) isConnected(x, y int) bool {
return uf.Find(x) == uf.Find(y)
}
func possibleBipartition(n int, dislikes [][]int) bool {
// 1. groups[i] 表示第i个人的讨厌组
groups := make([][]int, n)
for _, dislike := range dislikes {
// 转化为index - 1
x, y := dislike[0]-1, dislike[1]-1
groups[x] = append(groups[x], y)
groups[y] = append(groups[y], x)
}
// 2. 使用并查集检查连接性
uf := newUnionFind(n)
for x, group := range groups {
for _, y := range group {
// 讨厌组进行并查集合并
uf.Union(group[0], y)
// 如果讨厌组和当前值同组,则说明你不可行
if uf.isConnected(x, y) {
return false
}
}
}
return true
}
评论