原来这就是深度优先和广度优先

159 阅读3分钟

BFS, DFS也没那么难理解嘛

前言:

Hello, 大家好,我是Felix, 之前看那些大厂的面经的时候,经常会说到深度优先,广度优先的,当时觉得好高大上的词,后来我私下学习,通过一个比较生动形象的案例,也有点理解了。

好的,话不多说,我们直接上案例。

给定一个二维整数数组nums,代表某个城市与某个城市是否相连,里面的值只可能为0或者1

如nums【i】【j】= 1,表示 城市i与城市j相连,如果为0则表示不相连

现在定义只有连在一起的城市,组成一起就是一个省份,现在求这个数组共有多少个省份

PS: 不管直接相连,还是间接相连,都表示属于一个省份, 如下图,其实就是只有两个省份

image.png

那我们应该如何解题呢?

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就讲到这里啦!