BFS, DFS也没那么难理解嘛
前言:
Hello, 大家好,我是Felix, 之前看那些大厂的面经的时候,经常会说到深度优先,广度优先的,当时觉得好高大上的词,后来我私下学习,通过一个比较生动形象的案例,也有点理解了。
好的,话不多说,我们直接上案例。
给定一个二维整数数组nums,代表某个城市与某个城市是否相连,里面的值只可能为0或者1
如nums【i】【j】= 1,表示 城市i与城市j相连,如果为0则表示不相连
现在定义只有连在一起的城市,组成一起就是一个省份,现在求这个数组共有多少个省份
PS: 不管直接相连,还是间接相连,都表示属于一个省份, 如下图,其实就是只有两个省份
那我们应该如何解题呢?
1. 广度优先
我们可以按照城市一个一个遍历,然后找到和每个城市直接相连的城市,但是在这个过程中,为了避免重复,我们就要记录下每个城市是否已经访问过了,因此需要额外一个boolean类型的数组,长度就是城市的个数。那我们看下代码怎么实现吧。
public static int calcProvinces(int [][] citiesInfo) {
if (null == citiesInfo || citiesInfo.length < 1) return 0;
//获取到city的个数,创建一个布尔数组保存是否访问过
int cityNum = citiesInfo.length;
boolean[] isVisited = new boolean[cityNum];
int provinceNum =0;
//对每个城市遍历
for (int i = 0;i < cityNum;i ++) {
//进入循环时候,首先要考虑,该城市是否已经访问过,访问过的话,要跳过
if (isVisited[i])
continue;
//开始记录,把在一起的城市标为访问过
for (int j = 0;j < citiesInfo[i].length;j ++) {
if (!isVisited[j] && citiesInfo[i][j] == 1) {
isVisited[j] = true;
}
}
//代码走到这里表明,成功标记出一个省,省份加一
provinceNum ++;
}
return provinceNum;
}
分析: 可以发现广度优先就是先找最表层的一圈,找出来之后,表层数据找完,再深入寻找,所以是广度优先(Breadth-First Search, BFS)
2. 深度优先
这时候,大家应该会有感觉了,深度优先,那就是,比如我要找和城市A连接的城市,找到了B,那就再找和B连接的,一直找到底为止。代码如下:
public static int calcProvinces (int [] [] citiesInfo) {
if (null == citiesInfo || citiesInfo.length < 1) return 0;
int cityNum = citiesInfo.length;
boolean[] isVisited = new boolean[cityNum];
int provinceNum =0;
for (int i = 0;i < cityNum;i ++) {
//同样的,如果该城市已经被访问过,也要跳过的
if (isVisited[i])
continue;
for (int j = 0;j < citiesInfo[i].length;j ++) {
if (!isVisited[j]) {
//此时找到了和i城市相连的城市了,那就要继续找和这个城市相连的城市
dfs(j, citiesInfo, isVisited);
provinceNum ++;
}
}
}
return provinceNum;
}
private static void dfs(int j, int[][] citiesInfo, boolean[] isVisited) {
int[] cityInfo = citiesInfo[j];
for (int k = 0;k < cityInfo.length;k ++) {
if (!isVisited[k] && cityInfo[k] == 1) {
isVisited[k] = true;
dfs(k, citiesInfo, isVisited);
}
}
}
分析: 深度优先很时候逃不掉递归的调用,处此接触可能觉得有点难以理解, 多DEBUG看看,孰能生巧。(Depth-First Search, BFS)
今天的BFS, DFS就讲到这里啦!