← Daily Logs
Algorithms

Undirected Path (Edge List Reachability)

EasyJul 4, 2026graphdfsadjacency-list

Same DFS reachability check as before, except the input isn't an adjacency list — it's a flat list of edges. The only new work is turning `[['i','j'], ...]` into a graph, and doing it symmetrically since an undirected edge means each endpoint is a neighbour of the other.

The problem

Implement `undirectedPath(edges, source, target)` where `edges` is a list of `[nodeA, nodeB]` pairs describing an undirected graph. Return whether `target` is reachable from `source`.

Unlike the earlier `hasPath`, there's no adjacency list handed in — just edges — and the graph isn't directed, so an edge `['k', 'i']` means the traversal can go `k -> i` and `i -> k`.

The approach

`createGraphAdjacencyObjectFromEdgeList` does the format conversion once, up front: for every `[e1, e2]` pair it makes sure both keys exist in `graph`, then pushes `e2` onto `graph[e1]` *and* `e1` onto `graph[e2]` — that second push is what makes the edge undirected, since a directed adjacency list would only add one direction.

Once `graph` is built, the body is identical to the earlier `hasPath`: `source === target` short-circuits, then an iterative stack-based DFS with a `visited` set walks outward, returning `true` the moment `target` turns up as a neighbour.

Reusing `hasPath`'s traversal unchanged (just swapping the graph's construction) shows the adjacency-list shape is the real interface — DFS/BFS/reachability code doesn't care whether the graph started life as edges or was handed over pre-built, as long as it ends up looking the same.

The solution

js
export function createGraphAdjacencyObjectFromEdgeList(edges) {
    const graph = {}
    for (let edge of edges) {
        const [e1, e2] = edge
        if (!(e1 in graph)) graph[e1] = []
        if (!(e2 in graph)) graph[e2] = []
        graph[e1].push(e2)
        graph[e2].push(e1)
    }
    return graph
}

export function undirectedPath(edges, source, target) {
    const graph = createGraphAdjacencyObjectFromEdgeList(edges)
    if (source == target) return true
    const visited = new Set()
    visited.add(source)
    const stack = [source]
    while (stack.length) {
        const node = stack.pop()
        for (let neighbour of graph[node]) {
            if (!visited.has(neighbour)) {
                if (neighbour == target) {
                    return true
                }
                visited.add(neighbour)
                stack.push(neighbour)
            }

        }
    }
    return false
}

Time O(V + E)Space O(V)

All entries