Leetcode --- NO.785 判断二分图(Java)

题目描述

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

题目分析

  • 给定的数组的意思就是,对于示例一,就是说graph[0]有两个边,一个是0-1,一个是0-3graph[1]的两个边就是1-01-2
  • 题目最后的注意表明graph[i]不会包含i或者是重复值,且数组是对称的
  • 以矩阵的形式表示示例一中的graph数组
0 1 2 3
0
1
2
3
  • 以矩阵的形式表示示例二中的graph数组
0 1 2 3
0
1
2
3
  • 题目中表示,如果是二分图,则每一个边的两个点都是来自不同的集合,那么在示例二中,从graph[0]来看,可以分成{0}{1,2,3}两个子集,但是在graph[1]中,就不可以这样分了,所以示例二不是二分图。

解法分析

  • 一种是暴力解法,先根据第0个点,将其拆分成两个子集,然后继续逐个遍历,观察子集是否还会发生变化,一旦发生了变化,那么就可以返回false
  • 其实这道题本质上就是将点分成两个集合,而且是相邻的点是属于不同的集合里面的,类似于涂色问题,将相邻的色块涂成不同的颜色,再规定颜色的种类只有两种,如果有解则返回true,没有则返回false

代码

class Solution {
    public boolean isBipartite(int[][] graph) {
        // 初始化标记数组
        int[] visited = new int[graph.length];
        // 遍历所有结点元素
        for(int i = 0; i<graph.length; i++){
            // System.out.println("visited["+i+"]"+visited[i]);
            // 如果已经遍历过就不用再遍历了
            if(visited[i] == 0 && !dfs(graph, visited, 1, i)){
                return false;
            }
        }
        return true;
    }

    // 利用颜色标记区分两个不同的集合
    // 0->red ==> 1->blue 3->blue
    // 1->blue ==> 0->check color 2->red
    // ....以此类推
    // 0=>not colored   1=>red  -1=>blue
    // visited[] => 标记某个点是否被访问过  visited[node] = color
    public boolean dfs(int[][] graph, int[] visited, int color, int node){
        // 如果该点已经被上了色,那么就判断颜色是否正确
        if(visited[node] != 0) return visited[node] == color;
        // 给该点上色
        visited[node] = color;
        // 遍历相邻结点递归判断,并指定相邻结点的颜色,如果该点是红,那相邻的就是蓝;
        for(int i : graph[node]){
            if (!dfs(graph, visited, -color, i)) return false;
        }
        return true;
    }
}

猜你喜欢

转载自blog.csdn.net/Kobe_k/article/details/107378848