使用DFS和BFS统计省份数量
我们用一个二维数组来存储城市与城市之间的关系,若从城市i到城市j直接相连或间接相连,那么二维数组的[i][j]和[j][i]均为1,若无论如何也无法从一座城市抵达另外一座城市,则对应二维数组中两个值为0.约定城市到自己之间是连接的。
先来看看DFS.首先我们需要遍历一个存储了城市之间连通信息的二维数组,然后我们还需要一个数组来打标记,若某一座城市在遍历中已经被访问,那么以后遍历时,我们就不需要再访问了。由于二维数组长度就是城市数量,因此标记数组只需要开这么大。遍历时,我们就用两个for循环嵌套(这里涉及函数的调用,但本质上就是两个for循环嵌套),if判断时,我们不仅需要判断二维数组中两座城市之间是否相连,我们还需要判断在标记数组中是否被访问,判断后者可以减少时间复杂度。
1 private static void dfs(int i, int cities, boolean[] visited, int[][] citiesConnected) { 2 for(int j = 0;j < cities;++j){ 3 if(citiesConnected[i][j] == 1 && !visited[j]){ 4 visited[j] = true; //有关联,那么就打标记 5 //然后递归,因为找到了所有跟i直接相连的城市,我们还需要找没有跟i直接相连的城市 6 //也就是跟j直接相连的城市 7 dfs(j, cities, visited, citiesConnected); 8 } 9 } 10 }
1 private static int getProvincesByDepth(int[][] citiesConnected) { 2 int cities = citiesConnected.length; 3 int provinces = 0; 4 boolean[] visited = new boolean[cities]; 5 for(int i = 0;i < cities;++i){ 6 if(!visited[i]){ //因为在dfs方法里很多城市之间都打上了标记,因此这里其实会跳过很多城市 7 dfs(i, cities, visited, citiesConnected); 8 ++provinces; 9 } 10 } 11 return provinces; 12 }
再来看看广度优先:
我们就以某一座城市为中心,一圈一圈地挨个遍历,然后把这个圈子慢慢变大。所以这样一来一个while循环就足可以遍历完所有与这座城市相连的城市了。然后在外层for循环我们再找其他省份的城市。
1 private static void bfs(int i, int cities, boolean[] visited, int[][] citiesConnected) { 2 Queue<Integer> queue = new LinkedList<Integer> (); 3 queue.offer(i); 4 while(!queue.isEmpty()) //这么一个循环,就可以实现以某一座城市为中心,呈辐射状向四周散开全部遍历 5 { 6 int temp = queue.poll(); 7 visited[temp] = true; 8 for(int j = 0;j < cities;++j){ 9 if(citiesConnected[i][j] == 1 && !visited[j]) { 10 queue.offer(j); 11 } 12 } 13 } //循环结束后再去找没有被标记的城市实行同样的操作 14 }
1 private static int getProvincesByWidth(int[][] citiesConnected) { 2 int cities = citiesConnected.length; 3 int provinces = 0; 4 boolean[] visited = new boolean[cities]; 5 for(int i = 0;i < cities;++i){ 6 if(!visited[i]){ 7 bfs(i, cities, visited, citiesConnected); 8 ++provinces; 9 } 10 11 } 12 return provinces; 13 }
来看看运行效果:

贴一波完整代码:
1 package com.hw.list0710; 2 3 import java.util.LinkedList; 4 import java.util.Queue; 5 import java.util.Scanner; 6 7 public class GroupMerge { 8 private static int getProvincesByDepth(int[][] citiesConnected) { 9 int cities = citiesConnected.length; 10 int provinces = 0; 11 boolean[] visited = new boolean[cities]; 12 for(int i = 0;i < cities;++i){ 13 if(!visited[i]){ //因为在dfs方法里很多城市之间都打上了标记,因此这里其实会跳过很多城市 14 dfs(i, cities, visited, citiesConnected); 15 ++provinces; 16 } 17 } 18 return provinces; 19 } 20 21 private static int getProvincesByWidth(int[][] citiesConnected) { 22 int cities = citiesConnected.length; 23 int provinces = 0; 24 boolean[] visited = new boolean[cities]; 25 for(int i = 0;i < cities;++i){ 26 if(!visited[i]){ 27 bfs(i, cities, visited, citiesConnected); 28 ++provinces; 29 } 30 31 } 32 return provinces; 33 } 34 35 /** 36 * 深度优先 37 * @param i 38 * @param cities 39 * @param visited 40 * @param citiesConnected 41 */ 42 private static void dfs(int i, int cities, boolean[] visited, int[][] citiesConnected) { 43 for(int j = 0;j < cities;++j){ 44 if(citiesConnected[i][j] == 1 && !visited[j]){ 45 visited[j] = true; //有关联,那么就打标记 46 //然后递归,因为找到了所有跟i直接相连的城市,我们还需要找没有跟i直接相连的城市 47 //也就是跟j直接相连的城市 48 dfs(j, cities, visited, citiesConnected); 49 } 50 } 51 } 52 53 /** 54 * 广度优先 55 * @param i 56 * @param cities 57 * @param visited 58 * @param citiesConnected 59 */ 60 private static void bfs(int i, int cities, boolean[] visited, int[][] citiesConnected) { 61 Queue<Integer> queue = new LinkedList<Integer> (); 62 queue.offer(i); 63 while(!queue.isEmpty()) //这么一个循环,就可以实现以某一座城市为中心,呈辐射状向四周散开全部遍历 64 { 65 int temp = queue.poll(); 66 visited[temp] = true; 67 for(int j = 0;j < cities;++j){ 68 if(citiesConnected[i][j] == 1 && !visited[j]) { 69 queue.offer(j); 70 } 71 } 72 } //循环结束后再去找没有被标记的城市实行同样的操作 73 } 74 75 public static void main(String[] args) { 76 int[][] city = null; 77 Scanner s = new Scanner(System.in); 78 System.out.println("长度:"); 79 int length = s.nextInt(); 80 city = new int[length][length]; 81 System.out.println("输入数据:"); 82 for(int i = 0;i < length;++i) { 83 for(int j = 0;j < length;++j) { 84 city[i][j] = s.nextInt(); 85 } 86 } 87 s.close(); 88 int res1 = getProvincesByDepth(city); 89 System.out.println("使用深度优先:共有"+res1+"个省份"); 90 int res2 = getProvincesByWidth(city); 91 System.out.println("使用广度优先:共有"+res2+"个省份"); 92 } 93 }

浙公网安备 33010602011771号