🧠
Brute Force (Try All 2-Colorings via Backtracking)
💡 This approach tries every possible way to color the graph with two colors to check bipartiteness. It is extremely inefficient but helps understand the problem's nature and why smarter methods are needed.
Intuition
Try assigning colors to each node recursively, backtracking if a conflict arises. If any assignment works, the graph is bipartite.
Algorithm
- Initialize a color array with -1 (uncolored) for all nodes.
- Define a recursive function that tries to color a node with a given color.
- For each neighbor, if uncolored, recursively assign the opposite color; if colored and same as current, return false.
- Try all nodes (to cover disconnected graphs). If all succeed, return true.
💡 The recursion and backtracking make it hard to see efficiency, but it directly models the problem's definition.
from typing import List
def isBipartite(graph: List[List[int]]) -> bool:
n = len(graph)
color = [-1] * n
def dfs(node: int, c: int) -> bool:
if color[node] != -1:
return color[node] == c
color[node] = c
for nei in graph[node]:
if not dfs(nei, 1 - c):
return False
return True
for i in range(n):
if color[i] == -1:
if not dfs(i, 0):
return False
return True
# Driver code
if __name__ == '__main__':
graph1 = [[1,3],[0,2],[1,3],[0,2]]
graph2 = [[1,2],[0,2],[0,1]]
print(isBipartite(graph1)) # True
print(isBipartite(graph2)) # False
Line Notes
color = [-1] * nInitialize all nodes as uncolored to track assignments
def dfs(node: int, c: int) -> bool:Recursive function tries to color node with color c
if color[node] != -1:If node already colored, check for color conflict
color[node] = cAssign color c to current node
for nei in graph[node]:Traverse all neighbors to assign opposite color
if not dfs(nei, 1 - c):If neighbor coloring fails, propagate failure
for i in range(n):Check all nodes to cover disconnected components
if color[i] == -1:Start DFS only from uncolored nodes
import java.util.*;
public class IsGraphBipartite {
public static boolean isBipartite(int[][] graph) {
int n = graph.length;
int[] color = new int[n];
Arrays.fill(color, -1);
for (int i = 0; i < n; i++) {
if (color[i] == -1) {
if (!dfs(graph, color, i, 0)) return false;
}
}
return true;
}
private static boolean dfs(int[][] graph, int[] color, int node, int c) {
if (color[node] != -1) return color[node] == c;
color[node] = c;
for (int nei : graph[node]) {
if (!dfs(graph, color, nei, 1 - c)) return false;
}
return true;
}
public static void main(String[] args) {
int[][] graph1 = {{1,3},{0,2},{1,3},{0,2}};
int[][] graph2 = {{1,2},{0,2},{0,1}};
System.out.println(isBipartite(graph1)); // true
System.out.println(isBipartite(graph2)); // false
}
}
Line Notes
int[] color = new int[n];Create color array to track node colors
Arrays.fill(color, -1);Mark all nodes uncolored initially
if (color[i] == -1)Start DFS from uncolored nodes to cover all components
if (color[node] != -1) return color[node] == c;Check for color conflict if already colored
color[node] = c;Assign color to current node
for (int nei : graph[node])Traverse neighbors to assign opposite color
if (!dfs(...)) return false;Propagate failure if neighbor coloring fails
#include <iostream>
#include <vector>
using namespace std;
bool dfs(int node, int c, vector<int>& color, const vector<vector<int>>& graph) {
if (color[node] != -1) return color[node] == c;
color[node] = c;
for (int nei : graph[node]) {
if (!dfs(nei, 1 - c, color, graph)) return false;
}
return true;
}
bool isBipartite(const vector<vector<int>>& graph) {
int n = graph.size();
vector<int> color(n, -1);
for (int i = 0; i < n; i++) {
if (color[i] == -1) {
if (!dfs(i, 0, color, graph)) return false;
}
}
return true;
}
int main() {
vector<vector<int>> graph1 = {{1,3},{0,2},{1,3},{0,2}};
vector<vector<int>> graph2 = {{1,2},{0,2},{0,1}};
cout << boolalpha << isBipartite(graph1) << endl; // true
cout << boolalpha << isBipartite(graph2) << endl; // false
return 0;
}
Line Notes
vector<int> color(n, -1);Initialize color vector with -1 for uncolored nodes
if (color[node] != -1) return color[node] == c;Check if node already colored and matches expected color
color[node] = c;Assign color to current node
for (int nei : graph[node])Iterate over neighbors to assign opposite color
if (!dfs(...)) return false;Return false if neighbor coloring fails
for (int i = 0; i < n; i++)Check all nodes to cover disconnected components
if (color[i] == -1)Start DFS only from uncolored nodes
function isBipartite(graph) {
const n = graph.length;
const color = new Array(n).fill(-1);
function dfs(node, c) {
if (color[node] !== -1) return color[node] === c;
color[node] = c;
for (const nei of graph[node]) {
if (!dfs(nei, 1 - c)) return false;
}
return true;
}
for (let i = 0; i < n; i++) {
if (color[i] === -1) {
if (!dfs(i, 0)) return false;
}
}
return true;
}
// Test cases
console.log(isBipartite([[1,3],[0,2],[1,3],[0,2]])); // true
console.log(isBipartite([[1,2],[0,2],[0,1]])); // false
Line Notes
const color = new Array(n).fill(-1);Initialize color array with -1 for uncolored nodes
if (color[node] !== -1) return color[node] === c;Check if node already colored and matches expected color
color[node] = c;Assign color to current node
for (const nei of graph[node])Traverse neighbors to assign opposite color
if (!dfs(nei, 1 - c)) return false;Return false if neighbor coloring fails
for (let i = 0; i < n; i++)Check all nodes to cover disconnected components
if (color[i] === -1)Start DFS only from uncolored nodes
Each node and edge is visited once during DFS. Color array uses O(V) space.
💡 For n=1000 nodes and m=2000 edges, this means roughly 3000 operations, which is efficient enough.
Interview Verdict: Accepted
Though called brute force here, this DFS coloring is the standard approach and runs efficiently for large graphs.