【Garen刷题笔记】LeetCode 785.判断二分图

这篇博客详细介绍了如何解决LeetCode 785题——判断二分图。通过深度优先遍历(DFS)或广度优先遍历(BFS)结合染色法来判断图是否为二分图。在遍历过程中,遇到相邻节点颜色相同则返回False,否则给相邻节点染上不同颜色。遍历结束后,若所有节点都被染色,则图是二分图,返回True。注意要处理非连通图的情况。最后,分析了算法的时间复杂度为O(N+M)和空间复杂度为O(N)。

LeetCode 785.判断二分图(7.16日题)
题目:给定一个无向图graph,当这个图为二分图时返回true。
如果我们能将一个图的节点集合分割成两个独立的子集A和B,并使图中的每一条边的两个节点一个来自A集合,一个来自B集合,我们就将这个图称为二分图。
graph将会以邻接表方式给出,graph[i]表示图中与节点i相连的所有节点。每个节点都是一个在0到graph.length-1之间的整数。这图中没有自环和平行边: graph[i] 中不存在i,并且graph[i]中没有重复的值。
示例

思路

判断二分图的思想,就是遍历图+染色法,无向图的遍历可以采用深度优先遍历DFS和广度优先遍历BFS。染色法的算法流程如下:

  • 我们任选一个节点开始,将其染成红色,并从该节点开始对整个无向图进行遍历; 在遍历的过程中,如果我们通过节点 u 遍历到了节点 v(即 u 和 v 在图中有一条边直接相连),那么会有两种情况:
    • 如果 v 未被染色,那么我们将其染成与 u 不同的颜色,并对 v 直接相连的节点进行遍历;
    • 如果 v 被染色,并且颜色与 u 相同,那么说明给定的无向图不是二分图。我们可以直接退出遍历并返回 False 作为答案。
  • 当遍历结束时,说明给定的无向图是二分图,返回 True 作为答案。

注意:因题目未规定图一定为连通图,所以要遍历确保每一个节点被染色。

代码

class Solution {
    public boolean isBipartite(int[][] graph) {
        //BFS
        Queue<Integer> queue = new LinkedList<>();
        int n = graph.length;
        int[] color = new int[n];
        //图不一定联通,所以遍历
        for(int i = 0; i < n; ++i){
            if(color[i] == 0){
                queue.add(i);
                color[i] = 1;
                while(!queue.isEmpty()){
                    int node = queue.poll();
                    //遍历出队元素邻接点
                    for(int neighbor : graph[node]){
                        if(color[neighbor] == 0){
                            queue.add(neighbor);
                            color[neighbor] = color[node] == 1 ? 2 : 1;
                        }
                        if(color[neighbor] == color[node]){
                            return false;
                        }
                    }
                }
            }
        }
        return true;
    }
}

复杂度分析

时间复杂度:O(N+M)O(N+M)O(N+M),遍历每一个点,直至所有点被染色,遍历每一条边判断邻接关系,其中 NNNMMM 分别是无向图中的点数和边数。

空间复杂度:O(N)O(N)O(N),存储节点颜色的数组需要 O(N)O(N)O(N) 的空间,并且在广度优先搜索中维护一个队列,队列中最多有 N−1N-1N1 个节点,所以需要 O(N)O(N)O(N) 的空间。如果这里采用深度优先搜索遍历,则需要进行递归或维护一个栈,栈的最大深度为NNN,空间复杂度仍是O(N)O(N)O(N)

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值