Список смежности
graph := make([][]int, n)
graph[from] = append(graph[from], to)
Для плотного графа матрица проще, но требует O(V²) памяти.
Список смежности и visited превращают связи во множество достижимых вершин.
Минимальный синтаксис, который понадобится в решении.
graph := make([][]int, n)
graph[from] = append(graph[from], to)
Для плотного графа матрица проще, но требует O(V²) памяти.
seen := make([]bool, n)
seen[start] = true
Отмечай вершину перед рекурсией или enqueue.
Три идиоматичных решения на Go с оценкой времени и памяти.
Запускаем DFS из каждой непосещённой вершины.
O(V²) time · O(V) spacefunc findCircleNum(g [][]int) int {
seen, count := make([]bool, len(g)), 0
var dfs func(int)
dfs = func(v int) {
seen[v] = true
for next, edge := range g[v] {
if edge == 1 && !seen[next] { dfs(next) }
}
}
for v := range g { if !seen[v] { count++; dfs(v) } }
return count
}
Map связывает старый узел с уже созданной копией.
O(V + E) time · O(V) spacefunc cloneGraph(node *Node) *Node {
copies := map[*Node]*Node{}
var clone func(*Node) *Node
clone = func(n *Node) *Node {
if n == nil { return nil }
if copy, ok := copies[n]; ok { return copy }
copy := &Node{Val:n.Val}; copies[n] = copy
for _, next := range n.Neighbors { copy.Neighbors = append(copy.Neighbors, clone(next)) }
return copy
}
return clone(node)
}
DFS останавливается, как только достигает целевой вершины.
O(V + E) time · O(V + E) spacefunc validPath(n int, edges [][]int, source, target int) bool {
graph := make([][]int, n)
for _, e := range edges {
graph[e[0]] = append(graph[e[0]], e[1])
graph[e[1]] = append(graph[e[1]], e[0])
}
seen := make([]bool, n)
var dfs func(int) bool
dfs = func(v int) bool {
if v == target { return true }
seen[v] = true
for _, next := range graph[v] { if !seen[next] && dfs(next) { return true } }
return false
}
return dfs(source)
}