#785 Is Graph Bipartite?
the problem
In plain words
An undirected graph is given as adjacency lists graph[u]. Return true if the nodes can be split into two sets so that every edge goes between the sets. The graph may be disconnected.
in graph = [[1,2,3],[0,2],[0,1,3],[0,2]]
out false
0, 1, 2 form a triangle — an odd cycle can't be 2-coloured.
in graph = [[1,3],[0,2],[1,3],[0,2]]
out true
Sets {0, 2} and {1, 3}.
- 1 ≤ n ≤ 100
- No self-loops or parallel edges; u ∈ graph[v] ⇔ v ∈ graph[u]
your turn
Try it before you peek
Read the examples, say the brute force out loud, then write code: here or on LeetCode ↗. Stuck for 20 minutes? Open one hint at a time.
Solve it in the browser
LeetCode-style: complete the class. Compiled by the real javac (Java 17) and judged right here — nothing is sent anywhere.
Solutions are hidden so you can try first. Even 20 minutes of real effort makes the answer stick far better than reading it.
Marking the problem solved, or opening every hint, also shows it.
the aha
Key insight
patternBipartite check (two-colouring)
Paint the start A; every neighbour must be B, their neighbours A, and so on — the colouring is forced. A single edge with the same colour on both ends means "no".
solutions
From brute force to optimal
BFS from each unpainted node; paint neighbours the opposite colour; a same-colour neighbour is a conflict.
- color[] = 0 (unpainted), 1 or -1.
- For every unpainted start: paint 1, BFS.
- Unpainted neighbour → paint -color[u], enqueue. Same colour → return false.
Every node painted once, every edge checked twice.
Colour array plus queue.
class Solution { public boolean isBipartite(int[][] graph) { int n = graph.length; int[] color = new int[n]; for (int start = 0; start < n; start++) { // the graph may be disconnected if (color[start] != 0) continue; color[start] = 1; Deque<Integer> queue = new ArrayDeque<>(); queue.offer(start); while (!queue.isEmpty()) { int u = queue.poll(); for (int v : graph[u]) { if (color[v] == 0) { color[v] = -color[u]; queue.offer(v); } else if (color[v] == color[u]) return false; } } } return true; }}Dry run
Same forced colouring, recursively.
- paint(u, c): color[u] = c; for each neighbour: same colour → false; unpainted → paint(v, -c).
Same work as BFS.
Colour array plus recursion depth.
class Solution { private int[] color; // 0 = unpainted, 1 / -1 = the two sides public boolean isBipartite(int[][] graph) { color = new int[graph.length]; for (int s = 0; s < graph.length; s++) if (color[s] == 0 && !paint(graph, s, 1)) return false; return true; } private boolean paint(int[][] graph, int u, int c) { color[u] = c; for (int v : graph[u]) { if (color[v] == c) return false; // neighbour on my side if (color[v] == 0 && !paint(graph, v, -c)) return false; // paint it the other side } return true; }}All neighbours of u must be on the same side → union them together. If u ever shares a set with a neighbour, it fails.
- For each u, for each neighbour v: if find(u) == find(v) → false.
- Union v with u's first neighbour.
One find/union per edge; path halving alone keeps each O(log V) amortized.
The parent array.
class Solution { /** All neighbours of u must end up on the same side → union them; u must not join that group. */ public boolean isBipartite(int[][] graph) { int[] parent = new int[graph.length]; for (int i = 0; i < parent.length; i++) parent[i] = i; for (int u = 0; u < graph.length; u++) { for (int v : graph[u]) { if (find(parent, u) == find(parent, v)) return false; parent[find(parent, v)] = find(parent, graph[u][0]); // join v with u's first neighbour } } return true; } private int find(int[] parent, int x) { while (parent[x] != x) x = parent[x] = parent[parent[x]]; return x; }}in the room
How to say it in the interview
talk track
- Say: "Bipartite ⇔ no odd cycle ⇔ 2-colourable. I'll try to 2-colour with BFS."
- Explicitly loop over every node — the graph may be disconnected.
traps
- Only starting from node 0 — a conflict in another component is missed.
what they ask next
Follow-ups
Possible Bipartition (LC 886)?
Build the graph from the dislike pairs, then run exactly this check.
before you submit
Edge cases to test
- A node with no edges is fine on either side.
- The graph may be disconnected — the odd cycle can hide in a component that doesn't contain node 0.
- An even cycle (a square) is bipartite; any odd cycle (a triangle) is not.
practise next
Similar problems
- #207Course ScheduleMediumin Topo Sort
- #200Number of IslandsMediumin Graphs
- #990Satisfiability of Equality EquationsMediumin Union-Find & MST