剑指 Offer II 106. 二分图(785. 判断二分图)

题目:

 

 

 

思路:

【0】依据题意可知其实就是把联通的两个节点分别置于两个集合中,如示例2中,0与1联通,那么0放置于A集合,1放置于B集合,而0又与3联通,且此时0在A集合中,故只能把3放置于B集合中,然后2又与3联通故也只能放在A集合,此时全部元素都放入了集合之中,且不冲突则表示成功,若,存在某元素要放置于两个集合的话则不成功。

【1】深度优先搜索

【2】广度优先搜索

代码展示:

广度优先搜索的方式:

//时间1 ms击败49.43%
//内存43 MB击败5.21%
//时间复杂度:O(n+m),其中 n 和 m 分别是无向图中的点数和边数。
//空间复杂度:O(n),存储节点颜色的数组需要 O(n) 的空间,并且在广度优先搜索的过程中,队列中最多有 n−1 个节点,需要 O(n) 的空间。
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;
    }
}


//时间1 ms击败49.43%
//内存43.3 MB击败5.21%
class Solution {
    public boolean isBipartite(int[][] graph) {
        Queue<Integer> queue = new LinkedList<Integer>();
        int[] colour = new int[graph.length];
        for(int i=0; i<graph.length; i++) {
            if(colour[i] == 0) {
                queue.add(i);
                colour[i] = 1;
                
                while(!queue.isEmpty()) {
                    int cur = queue.poll();
                    
                    for(int next: graph[cur]) {
                        if(colour[cur] == colour[next]) {
                            return false;
                        }
                        if(colour[next] == 0) {
                            queue.add(next);
                            colour[next] = 1 == colour[cur] ? 2 :1;
                        }
                    }
                }       
            }
        }
        return true;
    }
}

 

 

 

深度优先搜索的方式:

//时间0 ms击败100%
//内存42.9 MB击败5.2%
//时间复杂度:O(n+m),其中 n 和 m 分别是无向图中的点数和边数。
//空间复杂度:O(n),存储节点颜色的数组需要 O(n) 的空间,并且在深度优先搜索的过程中,栈的深度最大为 n,需要 O(n) 的空间。
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;
        for (int neighbor : graph[node]) {
            //如果是没有存放颜色的,则进行上色
            if (color[neighbor] == UNCOLORED) {
                dfs(neighbor, cNei, graph);
                if (!valid) {
                    return;
                }
            } else if (color[neighbor] != cNei) {
                //如果存在颜色,且颜色不是目标颜色,则代表存在一个节点要上两种颜色,构不成二分图
                valid = false;
                return;
            }
        }
    }
}

 

posted @ 2023-04-14 16:19  忧愁的chafry  阅读(21)  评论(0)    收藏  举报