5/27 daily challenge: Possible Bipartition
My own solution, a bit faster than DFS(depth-first search):
func possibleBipartition(n int, dislikes [][]int) bool {
// key = ppl(1..n), val = group(0 or 1)
group := make(map[int]int)
ngroup := 0
for len(dislikes) > 0 {
skipped := make([][]int, 0)
for i := 0; i < len(dislikes); i++ {
a, b := dislikes[i][0], dislikes[i][1]
va, ea := group[a]
vb, eb := group[b]
switch {
case !ea && !eb:
if len(group) - ngroup == 0 {
// assign group to node a/b to trigger the loop
group[a] = 0
group[b] = 1
} else {
// if neither a nor b has been assigned a group, delay to next loop
skipped = append(skipped, dislikes[i])
}
case ea && !eb:
group[b] = 1 - va
case !ea && eb:
group[a] = 1 - vb
case ea && eb:
if va == vb {
return false
}
}
//fmt.Printf("len(group)=%v, group=%v\n", len(group), group)
//fmt.Printf("skipped=%v\n", skipped)
}
ngroup = len(group)
dislikes = skipped
}
return true
}
The DFS version:
func possibleBipartition(n int, dislikes [][]int) bool {
graph := make(map[int][]int)
for i := 0; i < len(dislikes); i++ {
a, b := dislikes[i][0], dislikes[i][1]
_, ea := graph[a]
_, eb := graph[b]
if !ea {
graph[a] = make([]int, 0)
}
if !eb {
graph[b] = make([]int, 0)
}
graph[a] = append(graph[a], b)
graph[b] = append(graph[b], a)
}
group := make([]int, n)
for i := 0; i < n; i++ {
group[i] = -1
}
for i := 1; i <= n; i++ {
if group[i-1] < 0 && !dfs(i, 0, graph, group) {
return false
}
}
return true
}
func dfs(i int, v int, graph map[int][]int, group []int) bool {
if group[i-1] < 0 {
group[i-1] = v
} else {
if group[i-1] != v {
return false
} else {
return true
}
}
_, exist := graph[i]
if exist {
for _, j := range graph[i] {
//fmt.Printf("graph[%v]=%v\n", i, graph[i])
if !dfs(j, 1-v, graph, group) {
return false
}
}
}
return true
}