Shortest Path Visiting All Nodes

HardBitmask · BFS over (node, mask)🧩 Bitmask DPLeetCode #847 ↗Updated

Problem

An undirected, connected graph with n nodes is given as an adjacency list (graph[i] = neighbours of i). Find the length (number of edges) of the shortest walk that visits every node. You may start and end anywhere, and revisit nodes and edges freely.
Input[[1,2,3],[0],[0],[0]]Output4 (1-0-2-0-3)
Input[[1],[0,2,4],[1,3,4],[2],[1,2]]Output4 (0-1-4-2-3)

1 ≤ n ≤ 12  ·  graph is undirected & connected  ·  no self-loops or parallel edges

Try it yourself

Java
class Solution {
    public int shortestPathLength(int[][] graph) {
        
    }
}
Your code is saved in this browser.Submit on LeetCode ↗
Key insight
The state is (node, visited set), not just the node. With n ≤ 12 the set is a bitmask → only n·2n ≈ 49k states, and a multi-source BFS over them finds the fewest steps to an all-ones mask.
PatternBitmask DP

Instinct n is tiny (about 20 or less) and you must use, visit or assign every item - make the set of used items a bitmask and DP over all 2^n subsets.

Memory hack Small n, big choice - let the bits keep score: each item is a light switch and the mask is the whole switch panel.

Open the Bitmask DP guide →

Approaches

Brute ForceAll Visit Orders + All-Pairs Distances

Time O(n · n!)Space O(n2)

A walk is fixed by the order of first visits; between consecutive ones, take the shortest path. So get all-pairs distances (Floyd–Warshall, O(n3)) and try every order.

Java
public int shortestPathLength(int[][] graph) {
    int n = graph.length, best = Integer.MAX_VALUE;
    int[][] d = allPairs(graph);
    for (int s = 0; s < n; s++) best = Math.min(best, orders(s, 1 << s, d));
    return best;
}
private int orders(int last, int mask, int[][] d) { // try every next node
    int n = d.length, best = mask == (1 << n) - 1 ? 0 : Integer.MAX_VALUE;
    for (int v = 0; v < n; v++)
        if ((mask >> v & 1) == 0)
            best = Math.min(best, d[last][v] + orders(v, mask | 1 << v, d));
    return best;
}
private int[][] allPairs(int[][] graph) { // Floyd-Warshall, unit edges
    int n = graph.length;
    int[][] d = new int[n][n];
    for (int i = 0; i < n; i++) {
        Arrays.fill(d[i], 1000);
        d[i][i] = 0;
        for (int j : graph[i]) d[i][j] = 1;
    }
    for (int k = 0; k < n; k++) for (int i = 0; i < n; i++) for (int j = 0; j < n; j++)
        d[i][j] = Math.min(d[i][j], d[i][k] + d[k][j]);
    return d;
}

Correct but factorial: 12! ≈ 4.8·108 orders.

At a glance

LevelApproachTimeSpace
Brute ForceAll Visit Orders + All-Pairs DistancesO(n · n!)O(n2)
BetterHeld–Karp Bitmask DPO(2n · n2)O(2n · n)
OptimalMulti-Source BFS on (node, mask)O(2n · n2)O(2n · n)
Common pitfalls
  • Marking nodes, not (node, mask) states, as seen.
  • Seeding BFS from one node — the walk may start anywhere.
  • Treating it as a Hamiltonian path — reuse is allowed.
Interview tips
  • n ≤ 12 is a bitmask hint (212 = 4096).
  • State = (position, visited set) → plain unit-weight BFS.
  • Relate it to TSP / Held–Karp.
Pattern
BFS / DP over (node, bitmask) → shortest path that must collect or visit a small set (≤ ~15) of items.
My notes saved in this browser