classSolution:defisBipartite(self,graph: List[List[int]]) ->bool: n =len(graph) colors = [0] * ndefdfs(i,color): colors[i]= colorfor neibor in graph[i]:if colors[neibor]== color:returnFalseif colors[neibor]==0andnotdfs(neibor,-1*color):returnFalsereturnTruefor i inrange(n):if colors[i]==0andnotdfs(i,1):returnFalsereturnTrue
并查集
思路
遍历图,对于每一个顶点 i,将其所有邻居进行合并,合并到同一个联通域中。这样当发现某个顶点 i 和其邻居已经在同一个联通分量的时候可以直接返回 false,否则返回 true。
代码
代码支持:Python3,Java
Python3 Code:
classUF:def__init__(self,n): self.parent ={}for i inrange(n): self.parent[i]= idefunion(self,i,j): self.parent[self.find(i)]= self.find(j)deffind(self,i):if i == self.parent[i]:return i self.parent[i]= self.find(self.parent[i])return self.parent[i]defis_connected(self,i,j):return self.find(i)== self.find(j)classSolution:defisBipartite(self,graph: List[List[int]]) ->bool: n =len(graph) uf =UF(n)for i inrange(n):for neibor in graph[i]:if uf.is_connected(i, neibor):returnFalse uf.union(graph[i][0], neibor)returnTrue
Java Code:
// weighted quick-union with path compressionclassSolution {classUF {int numOfUnions; // number of unionsint[] parent;int[] size; UF(int numOfElements) { numOfUnions = numOfElements; parent =newint[numOfElements]; size =newint[numOfElements];for (int i =0; i < numOfElements; i++) { parent[i] = i; size[i] =1; } }// find the head/representative of xintfind(int x) {while (x != parent[x]) { parent[x] = parent[parent[x]]; x = parent[x]; }return x; }voidunion(int p,int q) {int headOfP =find(p);int headOfQ =find(q);if (headOfP == headOfQ) {return; }// connect the small tree to the larger treeif (size[headOfP] < size[headOfQ]) { parent[headOfP] = headOfQ; // set headOfP's parent to be headOfQ size[headOfQ] += size[headOfP]; } else { parent[headOfQ] = headOfP; size[headOfP] += size[headOfQ]; } numOfUnions -=1; }booleanconnected(int p,int q) {returnfind(p)==find(q); } }publicbooleanisBipartite(int[][] graph) {int n =graph.length;UF unionfind =newUF(n);// i is what node each adjacent list is forfor (int i =0; i < n; i++) {// i's neighborsfor (int neighbor : graph[i]) {// i should not be in the union of its neighborsif (unionfind.connected(i, neighbor)) {returnfalse; }// add into unionsunionfind.union(graph[i][0], neighbor); } }returntrue; }
复杂度分析
令 v 和 e 为图中的顶点数和边数。
时间复杂度:$O(v+e)$, using weighted quick-union with path compression, where union, find and connected are $O(1)$, constructing unions takes $O(v)$
空间复杂度:$O(v)$ for auxiliary union-find space int[] parent, int[] space