LeetCode-判断二分图

1,804 阅读2分钟

算法记录

LeetCode 题目:

  存在一个无向图,图中有 n 个节点。其中每个节点都有一个介于 0 到 n - 1 之间的唯一编号。给你一个二维数组 graph ,其中 graph[u] 是一个节点数组,由节点 u 的邻接节点组成。形式上,对于 graph[u] 中的每个 v ,都存在一条位于节点 u 和节点 v 之间的无向边。

  如果能将一个图的节点集合分割成两个独立的子集 AB ,并使图中的每一条边的两个节点一个来自 A 集合,一个来自 B 集合,就将这个图称为 二分图 。


说明

一、题目

输入:graph = [[1,2,3],[0,2],[0,1,3],[0,2]]
输出:false
解释:不能将节点分割成两个独立的子集,以使每条边都连通一个子集中的一个节点与另一个子集中的一个节点。

二、分析

  • 按照题意中的二分图的含义,我们需要将整个无向图集中的所有子图内部的节点都划分为两类,相同类别内部没有互通的边。
  • 我们只需要按照图之间的先后顺序进行遍历,当前节点与下一个相邻节点之间标记不同的值,以此来划分出两个分类的数据节点。
  • 因为可能出现很多子图的情况,因此需要将每一个节点作为根节点进行一次遍历,这里如果根节点已经标记过就不用再往下了,节约时间。
  • 遍历过程中可能会出现一个节点已经被标记,但是由于其他节点的关系需要重新标记,这里存在两次标记的类别不同时就说明整个图不能划分二分类,可以快速失败,由一个状态值来标记。
class Solution {
    private boolean isRight = true;
    public boolean isBipartite(int[][] graph) {
        int[] color = new int[graph.length];
        for(int i = 0; i < graph.length && isRight; i++) {
            if(color[i] != 0) continue;
            isBipartite(color, graph, 1, i);
        }
        return isRight;
    }
    private void isBipartite(int[] color, int[][] graph, int c, int start) {
        color[start] = c;
        for(int temp : graph[start]) {
            if(color[temp] == 0) {
                isBipartite(color, graph, -c, temp);
                if(!isRight) return;
            } else if(color[temp] != -c) {
                isRight = false;
                return;
            }
        }
    }
}

总结

多图的深度遍历以及分类概念。