Welcome to Subscribe On Youtube
785. Is Graph Bipartite
Description
There is an undirected graph with n nodes, where each node is numbered between 0 and n - 1. You are given a 2D array graph, where graph[u] is an array of nodes that node u is adjacent to. More formally, for each v in graph[u], there is an undirected edge between node u and node v. The graph has the following properties:
- There are no self-edges (
graph[u]does not containu). - There are no parallel edges (
graph[u]does not contain duplicate values). - If
vis ingraph[u], thenuis ingraph[v](the graph is undirected). - The graph may not be connected, meaning there may be two nodes
uandvsuch that there is no path between them.
A graph is bipartite if the nodes can be partitioned into two independent sets A and B such that every edge in the graph connects a node in set A and a node in set B.
Return true if and only if it is bipartite.
Example 1:

Input: graph = [[1,2,3],[0,2],[0,1,3],[0,2]] Output: false Explanation: There is no way to partition the nodes into two independent sets such that every edge connects a node in one and a node in the other.
Example 2:

Input: graph = [[1,3],[0,2],[1,3],[0,2]]
Output: true
Explanation: We can partition the nodes into two sets: {0, 2} and {1, 3}.
Constraints:
graph.length == n1 <= n <= 1000 <= graph[u].length < n0 <= graph[u][i] <= n - 1graph[u]does not containu.- All the values of
graph[u]are unique. - If
graph[u]containsv, thengraph[v]containsu.
Solutions
Solution 1: Coloring Method to Determine Bipartite Graph
Traverse all nodes for coloring. For example, initially color them white, and use DFS to color the adjacent nodes with another color. If the target color to be colored is different from the color that the node has already been colored, it means that it cannot form a bipartite graph.
The time complexity is $O(n)$, and the space complexity is $O(n)$. Where $n$ is the number of nodes.
Solution 2: Union-Find
For this problem, if it is a bipartite graph, then all adjacent nodes of each vertex in the graph should belong to the same set and not be in the same set as the vertex. Therefore, we can use the union-find method. Traverse each vertex in the graph, and if it is found that the current vertex and its corresponding adjacent nodes are in the same set, it means that it is not a bipartite graph. Otherwise, merge the adjacent nodes of the current node.
The time complexity is $O(n \times \log n)$, and the space complexity is $O(n)$. Where $n$ is the number of nodes.
-
class Solution { private int[] color; private int[][] g; public boolean isBipartite(int[][] graph) { int n = graph.length; color = new int[n]; g = graph; for (int i = 0; i < n; ++i) { if (color[i] == 0 && !dfs(i, 1)) { return false; } } return true; } private boolean dfs(int u, int c) { color[u] = c; for (int v : g[u]) { if (color[v] == 0) { if (!dfs(v, 3 - c)) { return false; } } else if (color[v] == c) { return false; } } return true; } } // Solution 2 class Solution { private int[] p; public boolean isBipartite(int[][] graph) { int n = graph.length; p = new int[n]; for (int i = 0; i < n; ++i) { p[i] = i; } for (int a = 0; a < n; ++a) { for (int b : graph[a]) { int pa = find(a), pb = find(b); if (pa == pb) { return false; } p[pb] = find(graph[a][0]); } } return true; } private int find(int x) { if (p[x] != x) { p[x] = find(p[x]); } return p[x]; } } -
class Solution { public: bool isBipartite(vector<vector<int>>& graph) { int n = graph.size(); vector<int> color(n); for (int i = 0; i < n; ++i) if (!color[i] && !dfs(i, 1, color, graph)) return false; return true; } bool dfs(int u, int c, vector<int>& color, vector<vector<int>>& g) { color[u] = c; for (int& v : g[u]) { if (!color[v]) { if (!dfs(v, 3 - c, color, g)) return false; } else if (color[v] == c) return false; } return true; } }; // Solution 2 class Solution { public: bool isBipartite(vector<vector<int>>& graph) { int n = graph.size(); vector<int> p(n); iota(p.begin(), p.end(), 0); auto find = [&](this auto&& find, int x) -> int { if (p[x] != x) { p[x] = find(p[x]); } return p[x]; }; for (int a = 0; a < n; ++a) { for (int b : graph[a]) { int pa = find(a), pb = find(b); if (pa == pb) { return false; } p[pb] = find(graph[a][0]); } } return true; } }; -
class Solution: def isBipartite(self, graph: List[List[int]]) -> bool: def dfs(u, c): color[u] = c for v in graph[u]: if not color[v]: if not dfs(v, 3 - c): return False elif color[v] == c: return False return True n = len(graph) color = [0] * n for i in range(n): if not color[i] and not dfs(i, 1): return False return True # Solution 2 class Solution: def isBipartite(self, graph: List[List[int]]) -> bool: def find(x: int) -> int: if p[x] != x: p[x] = find(p[x]) return p[x] p = list(range(len(graph))) for a, bs in enumerate(graph): for b in bs: pa, pb = find(a), find(b) if pa == pb: return False p[pb] = find(bs[0]) return True -
func isBipartite(graph [][]int) bool { n := len(graph) color := make([]int, n) var dfs func(u, c int) bool dfs = func(u, c int) bool { color[u] = c for _, v := range graph[u] { if color[v] == 0 { if !dfs(v, 3-c) { return false } } else if color[v] == c { return false } } return true } for i := range graph { if color[i] == 0 && !dfs(i, 1) { return false } } return true } // Solution 2 func isBipartite(graph [][]int) bool { n := len(graph) p := make([]int, n) for i := range p { p[i] = i } var find func(x int) int find = func(x int) int { if p[x] != x { p[x] = find(p[x]) } return p[x] } for a, bs := range graph { for _, b := range bs { pa, pb := find(a), find(b) if pa == pb { return false } p[pb] = find(bs[0]) } } return true } -
function isBipartite(graph: number[][]): boolean { const n = graph.length; let valid = true; let colors = new Array(n).fill(0); function dfs(idx: number, color: number, graph: number[][]) { colors[idx] = color; const nextColor = 3 - color; for (let j of graph[idx]) { if (!colors[j]) { dfs(j, nextColor, graph); if (!valid) return; } else if (colors[j] != nextColor) { valid = false; return; } } } for (let i = 0; i < n && valid; i++) { if (!colors[i]) { dfs(i, 1, graph); } } return valid; } // Solution 2 function isBipartite(graph: number[][]): boolean { const n = graph.length; const p: number[] = Array.from({ length: n }, (_, i) => i); const find = (x: number): number => { if (x !== p[x]) { p[x] = find(p[x]); } return p[x]; }; for (let a = 0; a < n; ++a) { for (const b of graph[a]) { const [pa, pb] = [find(a), find(b)]; if (pa === pb) { return false; } p[pb] = find(graph[a][0]); } } return true; } -
impl Solution { #[allow(dead_code)] pub fn is_bipartite(graph: Vec<Vec<i32>>) -> bool { let mut graph = graph; let n = graph.len(); let mut color_vec: Vec<usize> = vec![0; n]; for i in 0..n { if color_vec[i] == 0 && !Self::traverse(i, 1, &mut color_vec, &mut graph) { return false; } } true } #[allow(dead_code)] fn traverse( v: usize, color: usize, color_vec: &mut Vec<usize>, graph: &mut Vec<Vec<i32>> ) -> bool { color_vec[v] = color; for n in graph[v].clone() { if color_vec[n as usize] == 0 { // This node hasn't been colored if !Self::traverse(n as usize, 3 - color, color_vec, graph) { return false; } } else if color_vec[n as usize] == color { // The color is the same return false; } } true } } // Solution 2 impl Solution { pub fn is_bipartite(graph: Vec<Vec<i32>>) -> bool { let n = graph.len(); let mut p: Vec<usize> = (0..n).collect(); fn find(x: usize, p: &mut Vec<usize>) -> usize { if p[x] != x { p[x] = find(p[x], p); } p[x] } for a in 0..n { for &b in &graph[a] { let pa = find(a, &mut p); let pb = find(b as usize, &mut p); if pa == pb { return false; } p[pb] = find(graph[a][0] as usize, &mut p); } } true } }