comments | difficulty | edit_url | tags | ||||
---|---|---|---|---|---|---|---|
true |
Medium |
|
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
v
is ingraph[u]
, thenu
is ingraph[v]
(the graph is undirected). - The graph may not be connected, meaning there may be two nodes
u
andv
such 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 == n
1 <= n <= 100
0 <= graph[u].length < n
0 <= graph[u][i] <= n - 1
graph[u]
does not containu
.- All the values of
graph[u]
are unique. - If
graph[u]
containsv
, thengraph[v]
containsu
.
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
class Solution:
def isBipartite(self, graph: List[List[int]]) -> bool:
def dfs(a: int, c: int) -> bool:
color[a] = c
for b in graph[a]:
if color[b] == c or (color[b] == 0 and not dfs(b, -c)):
return False
return True
n = len(graph)
color = [0] * n
for i in range(n):
if color[i] == 0 and not dfs(i, 1):
return False
return True
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 a, int c) {
color[a] = c;
for (int b : g[a]) {
if (color[b] == c || (color[b] == 0 && !dfs(b, -c))) {
return false;
}
}
return true;
}
}
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;
}
};
func isBipartite(graph [][]int) bool {
n := len(graph)
color := make([]int, n)
var dfs func(int, int) bool
dfs = func(a, c int) bool {
color[a] = c
for _, b := range graph[a] {
if color[b] == c || (color[b] == 0 && !dfs(b, -c)) {
return false
}
}
return true
}
for i := range graph {
if color[i] == 0 && !dfs(i, 1) {
return false
}
}
return true
}
function isBipartite(graph: number[][]): boolean {
const n = graph.length;
const color: number[] = Array(n).fill(0);
const dfs = (a: number, c: number): boolean => {
color[a] = c;
for (const b of graph[a]) {
if (color[b] === c || (color[b] === 0 && !dfs(b, -c))) {
return false;
}
}
return true;
};
for (let i = 0; i < n; i++) {
if (color[i] === 0 && !dfs(i, 1)) {
return false;
}
}
return true;
}
impl Solution {
pub fn is_bipartite(graph: Vec<Vec<i32>>) -> bool {
let n = graph.len();
let mut color = vec![0; n];
fn dfs(a: usize, c: i32, graph: &Vec<Vec<i32>>, color: &mut Vec<i32>) -> bool {
color[a] = c;
for &b in &graph[a] {
if color[b as usize] == c
|| (color[b as usize] == 0 && !dfs(b as usize, -c, graph, color))
{
return false;
}
}
true
}
for i in 0..n {
if color[i] == 0 && !dfs(i, 1, &graph, &mut color) {
return false;
}
}
true
}
}
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
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
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> 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;
}
};
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;
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 {
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
}
}