剑指 Offer II 106. 二分图——染色法+BFS(Java)

 

目录

1.题目

2.思路

时间复杂度——O(N + M)

空间复杂度——O(N)

3.结果

1.题目

2.思路

主要在于理解二分图的概念。可以把节点分成两个集合X 和 Y, 集合内的节点没有直接相连的边,允许间接相连。图中所有的边,其实一个节点必然来源于X, 一个节点来源于Y。

需要注意的一点是,这个图可能并不是完全联通的。

这道题的思路可以把求两个独立的集合转化为给图中所有的点涂两种不同的颜色。

如果两个点有连接的边,那他们的颜色一定不同,假如出现矛盾的地方,那说明两种颜色满足不了,所以不满足二分图的性质,直接返回false.

  • 用一个数组vis[]来记录图中节点的颜色。
  • 如果vis[i] == 1, 说明给这个节点涂上了第一种颜色。(二分图中集合X)
  • 如果vis[i] == -1, 说明给这个节点涂上了第二种颜色。(二分图中集合Y)
  • 如果vis[i] == 0 ,说明是第一次访问,任意赋值一个颜色即可, 比如vis[i] = 1, 并且开始BFS。
  • 由于图并不是完全联通,所以存在多个BFS的情况。注意剪枝。
  • 剪枝:在BFS中,队列中存储节点的值,以及节点的flag.如果flag为1,代表染第一种颜色,也就是vis[i]必须为1,如果此时vis[i] = -1, 那么说明之前已经访问过并且染色了,说明出现矛盾,返回false。flag为-1的情况也类似。

时间复杂度——O(N + M)

N为图的节点个数。M为图的边数。因为存在剪枝的关系,所以每个边只会访问一次。节点只会访问一次。

空间复杂度——O(N)

队列存储,以及vis数组都是O(N)

class Solution {
    public boolean isBipartite(int[][] graph) {
        // 染色法
        int n = graph.length;
        int[]vis = new int[n];
        Deque<int[]>d = new ArrayDeque();

        for(int i = 0 ; i < n ; i++){
            if(vis[i] == 0){
                d.addLast(new int[]{i, 1});
                while(!d.isEmpty()){
                    int[]temp = d.pollFirst();
                    int cur = temp[0], flag = temp[1];
                    if(flag == 1){
                        if(vis[cur] == 0 || vis[cur] == 1){
                            if(vis[cur] == 0)
                                vis[cur] = 1;
                            else
                                continue;
                        }  
                        else
                            return false;
                    }
                    else{
                        if(vis[cur] == 0 || vis[cur] == -1){
                            if(vis[cur] == -1)
                                continue;
                            vis[cur] = -1;
                        }
                        else
                            return false;
                    }
                    int[]g = graph[cur];
                    for(int j : g){
                        d.addLast(new int[]{j, -flag});
                    }
                }
            }
        }
        return true;
    
    }
}

3.结果

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值