Is Graph Bipartite?

MediumGraphs · DFS 2-Colouring🧩 Graph DFSLeetCode #785 ↗Updated

Problem

An undirected graph with nodes 0..n-1 is given as an adjacency list graph, where graph[u] holds the neighbours of u. Decide whether the nodes can be split into two groups so that every edge connects a node of one group to a node of the other. The graph may be disconnected.
Input[[1,2,3],[0,2],[0,1,3],[0,2]]Outputfalse
Input[[1,3],[0,2],[1,3],[0,2]]Outputtrue

1 ≤ n ≤ 100  ·  no self-loops or parallel edges  ·  if v ∈ graph[u] then u ∈ graph[v]

Try it yourself

Java
class Solution {
    public boolean isBipartite(int[][] graph) {
        
    }
}
Your code is saved in this browser.Submit on LeetCode ↗
Key insight
Bipartite ⇔ 2-colourable ⇔ no odd cycle. Once one node's colour is picked, every neighbour's colour is forced — so a single traversal per component either colours it consistently or hits an edge whose ends share a colour.
PatternGraph DFS

Instinct Connected regions, all paths, reachability, cloning or 2-colouring a graph or grid: dive from a node, mark it, recurse into unvisited neighbours.

Memory hack Mark before you march: go deep, paint as you go, and back up only when every door is already painted.

Open the Graph DFS guide →

Approaches

Brute ForceBacktracking over All 2-Colourings

Time O(2n·(V+E))Space O(n)

Place nodes one by one on side 1 or 2, skipping a side if an already-placed neighbour sits there; backtrack on a dead end. It ignores that colours are forced, so a late conflict re-tries choices for unrelated components — exponential.

Java
public boolean isBipartite(int[][] graph) {
    return place(graph, new int[graph.length], 0); // side: 0 = unset, 1 or 2
}
private boolean place(int[][] g, int[] side, int u) {
    if (u == g.length) return true; // every node placed, no clash
    for (int s = 1; s <= 2; s++) {
        boolean clash = false;
        for (int v : g[u]) if (side[v] == s) clash = true;
        if (clash) continue;
        side[u] = s;
        if (place(g, side, u + 1)) return true;
    }
    side[u] = 0;
    return false;
}

Literal search of every split; hopeless beyond ~25 nodes.

At a glance

LevelApproachTimeSpace
Brute ForceBacktracking over All 2-ColouringsO(2n·(V+E))O(n)
BetterUnion-Find on “Same Side”O((V+E)·log V)O(V)
OptimalDFS Two-ColouringO(V + E)O(V)
Common pitfalls
  • Starting only from node 0 — misses odd cycles in other components.
  • Using 0 both as “uncoloured” and as a colour.
  • Only checking uncoloured neighbours — the same-colour clash is the whole test.
Interview tips
  • State the equivalence: bipartite ⇔ 2-colourable ⇔ no odd cycle.
  • Point out colours are forced after the first pick — why no backtracking is needed.
  • Mention Union-Find if edges arrive online.
Pattern
Graph 2-colouring (DFS/BFS) → split items into two conflict-free groups.
My notes saved in this browser