应对笔试手写代码,如何准备深度优先算法 & 广度优先算法?

应对笔试手写代码,如何准备深度优先算法 & 广度优先算法?

  • 1. 什么是深度优先算法?什么又是广度优先算法?
  • 2. 广度优先算法使用场景
  • 3. 广度优先算法模板
  • 4. 深度优先算法使用场景
  • 5. 深度优先算法模板
  • 6. BFS 和 DFS 的复杂度
  • 7. BFS 和 DFS 实现方式

1. 什么是深度优先算法?什么又是广度优先算法?

这么高大上的名字,听起来是不是一脸懵逼,别着急,我给大家举一个通俗的例子,不知道大家有没有看过《小蝌蚪找妈妈》的故事,现在我就用这个例子给大家解释。

下面我画的图优点丑,不过可以凑合看。
应对笔试手写代码,如何准备深度优先算法 & 广度优先算法?_第1张图片
上面小蝌蚪在0号位置,它想找他的母亲可能出现在最后一层,那么小蝌蚪可以怎么走呢?

如果是按照广度优先搜索,小蝌蚪可以按照每一层找路径,最后,查找的结果就是#0#1#2#3#4#5…

如果是按照深度优先搜索,小蝌蚪可以按照一条路线走到底,走完后再返回原来的分叉点,选择别的路继续走,直到走完。查找的结果是#0#2#6#14#13#5#12#11#1#4#10…

(ps:深度优先算法也叫做DFS,广度优先算法也叫做BFS)

2. 广度优先算法使用场景

1、连通块问题
包括图、树、二维数组(矩阵)等等,即通过一个点扩散,找到一整个连通块。
2、层次遍历
给你一棵树,按每一层输出。
给你一个简单图(无方向、无权重),求最短路径。(其实和树的遍历是一样的,只不过图可能会遍历到重复节点,我们只需要每次去重即可,最后取最先到达目标节点时的层数即可)。
3、拓扑排序
给你一个当方向的图,求出他的拓扑排序,或者问是否有拓扑排序,或者求拓扑排序中最小的,或者问是否唯一(本质是一样的)。经典的问题就是说上某一节课之前需要上另一节课,现在给你若干课程并且有些课需要其他课线上才行,问你应该怎么安排课程。此时你把科目画出来,加上方向,就是拓扑问题了。

3. 广度优先算法模板

class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> res = new ArrayList<>();
        if(root == null){
            return res;
        }
        // 1. 定义队列
        Queue<TreeNode> queue = new LinkedList<>();
        // 2.加入初始条件
        queue.offer(root);
        // 3. 队列不为空的while循环
        while(!queue.isEmpty()){
            List<Integer> oneRes = new ArrayList<>();
            int n = queue.size();
            // 3.1 for循环将队列元素逐一取出进行处理
            for(int i = 0;i < n;++i){
                TreeNode temp = queue.poll();
                // 3.0 业务处理
                oneRes.add(temp.val);
                // 3.2 将下一条件放入队列中
                if(temp.left!=null){
                    queue.offer(temp.left);
                }
                if(temp.right!=null){
                    queue.offer(temp.right);
                }
            }
            // 3.3 将符合条件的一种结果放入结果集中
            res.add(oneRes);
        }
        // 4. 返回结果集
        return res;
    }
}

另外,关于二叉树的序列化和反序列化问题,也可以用广度优先算法来实现,如果题目指定使用哪种方法,广度优先算法序列化会比深度优先算法更直观。

4. 深度优先算法使用场景

1、图或者树的遍历(包括二叉树的遍历、连通图等)(有时候并不是明显的图或者树,而是需要自己手动模拟树或者图)。
2、排列(给定一些元素,返回所有可能的排列)(例如(1、2、3),排列有(123)(132)(213)(231)(312)(321))。
3、组合(给定一些元素,返回所有可能的组合)(例如(1、2、3),组合有(空)(1)(2)(3)(12)(13)(23)(123))。

在操作排列组合的时候,有时候会有重复的元素导致结果重复,除了用 HashSet 去重外,使用选代表的方法更合适,选代表就是选出一个合适的代表,其余重复元素直接忽略。

5. 深度优先算法模板

//模板2
void dfs()//参数用来表示状态  
{  
    if(到达终点状态){  
        ...//根据题意添加  
        return;  
    }  
    if(越界或者是不合法状态)  
        return;  
    if(特殊状态)//剪枝
        return ;
    for(扩展方式){  
        if(扩展方式所达到状态合法){  
            修改操作;//根据题意来添加  
            标记;  
            dfs();  
            (还原标记)//是否还原标记根据题意  
            //如果加上(还原标记)就是 回溯法  
        }  
 
    }  
}  

6. BFS 和 DFS 的复杂度

时间复杂度都是:O(V+E),V为顶点个数,E为边个数
BFS 的空间复杂度为队列大小,与宽度有关。
DFS 的空间复杂度为调用递归时的占用空间,与深度有关。

7. BFS 和 DFS 实现方式

BFS 一般是通过队列实现。
DFS 一般是通过递归实现。

你可能感兴趣的:(执章学长-数据结构与算法,算法,深度优先,宽度优先)