java数据结构与算法刷题-----LeetCode785. 判断二分图

java数据结构与算法刷题目录(剑指Offer、LeetCode、ACM)-----主目录-----持续更新(进不去说明我没写完):https://blog.csdn.net/grd_java/article/details/123063846

在这里插入图片描述
在这里插入图片描述

二分图:将所有结点分成两个集合,每条边的两个顶点处于不同的集合中。或者说图中顶点分成红色和绿色的两种。一条边相连的顶点(邻居),必须不同颜色。将相同颜色的顶点划分到一个集合。如果能够实现,就是二分图。
只要相邻(一条边相连的两个)顶点,颜色一样,就不是二分图

深度优先

解题思路:时间复杂度O( n + m n+m n+m),n是顶点个数,m是边的数量,空间复杂度O( n n n),保存每个顶点的颜色信息
  1. 为每个顶点上色,红色和绿色
  2. 如果当前顶点为红色,相邻的顶点必须是绿色
  3. 如果相邻的顶点已经上色,并且和当前顶点颜色相同,就不是二分图
  4. 也就是说,保证一条边相连顶点颜色不同,如果整个图都满足就是二分图,只要有任何一条边的两个顶点颜色相同就不是二分图
代码

在这里插入图片描述

class Solution {
    private static final int UNCOLORED = 0;//标志一个结点为无颜色
    private static final int RED = 1;//标志一个结点为红颜色
    private static final int GREEN = 2;//标志一个结点为绿颜色
    private int[] color;//结点颜色
    private boolean valid;//是否是二分图

    public boolean isBipartite(int[][] graph) {
        int n = graph.length;//结点个数
        valid = true;//初始认为当前图是二分图
        color = new int[n];//结点颜色初始都是无颜色
        Arrays.fill(color, UNCOLORED);
        for (int i = 0; i < n && valid; ++i) {//如果已经确定不是二分图,可以提前退出
            if (color[i] == UNCOLORED) {//如果无颜色,就进行深度优先遍历操作
                dfs(i, RED, graph);//第一个结点都从红色开始赋值
            }
        }
        return valid;//
    }

    public void dfs(int node, int c, int[][] graph) {
        color[node] = c;
        int cNei = c == RED ? GREEN : RED;//和c相反的颜色,例如c是红色,c的邻居cNei就必须是绿色
        for (int neighbor : graph[node]) {//获取其邻居
            if (color[neighbor] == UNCOLORED) {//如果是第一次上色
                dfs(neighbor, cNei, graph);//进行上色(与c相反)
                if (!valid) {//如果已经确定不是二分图,直接返回
                    return;
                }
            } else if (color[neighbor] != cNei) {//如果已经有颜色了,但是和当前结点的颜色c一样
                valid = false;//破坏了邻居颜色不一样的规则,不是二分图
                return;
            }
        }
    }
}

广度优先

解题思路:时间复杂度O( n + m n+m n+m),n是顶点个数,m是边的数量,空间复杂度O( n n n),保存每个顶点的颜色信息
  1. 将深度优先改为广度优先即可
  2. 但是因为使用了队列,根本上还是和深度优先一样的逻辑。肯定没有深度优先遍历直接底层用系统的栈空间快
  3. 实际工作场景的差别不大,但是做题嘛,1ms都能拉开很大差距。所以能深度优先深度优先遍历
代码

在这里插入图片描述

class Solution {
    private static final int UNCOLORED = 0;//无颜色
    private static final int RED = 1;//红色
    private static final int GREEN = 2;//绿色
    private int[] color;//颜色

    public boolean isBipartite(int[][] graph) {
        int n = graph.length;//顶点个数
        color = new int[n];//每个顶点颜色,默认无色
        // Arrays.fill(color, UNCOLORED);
        for (int i = 0; i < n; ++i) {//遍历每个顶点
            if (color[i] == UNCOLORED) {//如果无色
                Queue<Integer> queue = new LinkedList<Integer>();//对其进行广度优先
                queue.offer(i);//广度优先
                color[i] = RED;//第一个为红色,邻居为绿色
                while (!queue.isEmpty()) {//广度优先遍历其邻居
                    int node = queue.poll();//出队列其本身
                    int cNei = color[node] == RED ? GREEN : RED;//与其不同色,为邻居应有颜色
                    for (int neighbor : graph[node]) {//访问其邻居
                        if (color[neighbor] == UNCOLORED) {//如果没有访问过
                            queue.offer(neighbor);//广度优先
                            color[neighbor] = cNei;//赋值不同色
                        } else if (color[neighbor] != cNei) {//已经访问过,但是和当前顶点颜色一样
                            return false;//不是二分图
                        }
                    }
                }
            }
        }
        return true;//整个图都满足邻居颜色不同,就是二分图
    }
}
  • 20
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

殷丿grd_志鹏

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值