Problem Statement in English
You’re given an undirected graph, return true if and only if it is bipartite.
Approach
There are 2 approaches to solve this problem, one is using BFS and the other is using DSU. In both approaches, we will try to color the graph using 2 colors. If we can color the graph using 2 colors, then the graph is bipartite.
BFS: We will start from an unvisited node and color it with color 1. Then we will color all its neighbors with color -1. Then we will color all the neighbors of the neighbors with color 1 and so on. If we find a neighbor which is already colored with the same color as the current node, then the graph is not bipartite.
DSU: We will use DSU to group the nodes. We will iterate through the graph and for each node, we will try to union it with its neighbors. If we find a neighbor which is already in the same group as the current node, then the graph is not bipartite.
Solution in Python
- BFS Solution, Time: $O(n + m)$, Space: $O(n)$
class Solution:
def isBipartite(self, graph: List[List[int]]) -> bool:
l = len(graph)
color = [0 for _ in range(l)]
def bfs(node):
q = deque([node])
while q:
node = q.popleft()
if not color[node]:
color[node] = 1
for nei in graph[node]:
if not color[nei]:
color[nei] = -1 * color[node]
q.append(nei)
elif color[node] == color[nei]:
return False
return True
for i in range(l):
if not color[i] and not bfs(i):
return False
return True
- DSU Solution, Time: $O(n + m)$, Space: $O(n)$
class Solution:
def isBipartite(self, graph: List[List[int]]) -> bool:
parent = {}
def find(x):
if x not in parent:
parent[x] = x
if parent[x] != x:
parent[x] = find(parent[x])
return parent[x]
def union(a, b):
pa, pb = find(a), find(b)
parent[b] = pa
adj = defaultdict(list)
for i, l in enumerate(graph):
for element in l:
adj[i].append(element)
adj[element].append(i)
for i in range(len(graph)):
nei = adj[i]
this = find(i)
if not nei: continue
for j in nei[1:]:
if this == find(j):
return False
union(nei[0], j)
return True
And we are done.