剑指 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; } } } }

浙公网安备 33010602011771号