给定一个graph
,true
当且仅当它是二分的。
回想一下,如果我们可以将它的一组节点分成两个独立的子集A和B,使得图中的每条边在A中有一个节点,并且在B中有另一个节点,那么图是二分的。
该图形以下列形式给出:graph[i]
是j
节点之间的边缘i
和j
存在的索引列表。每个节点是0
和之间的整数graph.length - 1
。没有自我边缘或平行边缘:graph[i]
不包含i
,也不包含任何元素两次。
Example 1:
Input: [[1,3], [0,2], [1,3], [0,2]]
Output: true
Explanation:
The graph looks like this:
0----1
| |
| |
3----2
We can divide the vertices into two groups: {0, 2} and {1, 3}.
Example 2:
Input: [[1,2,3], [0,2], [0,1,3], [0,2]]
Output: false
Explanation:
The graph looks like this:
0----1
| \ |
| \ |
3----2
We cannot find a way to divide the set of nodes into two independent ubsets.
这是一道关于二部图的问题。
解题的思路分两部分,首先深度搜索得到连通图,在深度搜索时,对于iscolor数组,第一层标记为1,第二层标记为-1,第三层标记为1......如此往复。然后得到连通图,判断是否为二分图。如果所有的连通图都是二分图,那么返回true。
class Solution {
public boolean isBipartite(int[][] graph) {
boolean flag=true;
int length=graph.length;
if(length<3)
return true;
//初始化用来表示是否访问过,0表示未访问, 1,-1代表两种上色颜色
int[] iscolor=new int[length];
for(int i=0;i<length;i++) {
if(iscolor[i]==0) {
//进行深度优先搜索得到连通图
Set<Integer> set=new HashSet<Integer>();
GetGraphbyDFS(graph,iscolor,i,set,1);
if(!isvalid(set,graph,iscolor))
return false;
}
}
return true;
}
private boolean isvalid(Set<Integer> set, int[][] graph, int[] iscolor) {
// 判断是否是二分图
if(set.size()<=2)
return true;
for(Integer s: set){
for(int i=0;i<graph[s].length;i++) {
int index=graph[s][i];
if(iscolor[index]==iscolor[s])
return false;
}
}
return true;
}
private void GetGraphbyDFS(int[][] graph, int[] iscolor, int index, Set<Integer> set,int color) {
// TODO Auto-generated method stub
set.add(index);
iscolor[index]=color;
for(int i=0;i<graph[index].length;i++) {
if(iscolor[graph[index][i]]==0) {
GetGraphbyDFS(graph,iscolor,graph[index][i],set,-color);//下一次更换color
}
}
}
}