注:拿到题目后先通过审题,判断是哪一类题,可以套用什么模板,明确这一块非常重要没有之一,明确了之后,很可能出现自己都不知道是为什么,但题已经迎刃而解了!!!
一、二叉树问题
注:二叉树的遍历方式主要有广度遍历(BFS)和深度遍历(DFS),深度遍历又主要包含:先序遍历、中序遍历和后序遍历;
二者区别及适用范围:
(1)BFS、DFS 最坏时间复杂度相同,但是相比之下 BFS 更高效;
(2)DFS 的空间复杂度优于 BFS,且 DFS 使用递归,代码比较好些;
(3)一般在寻找最短路径时使用BFS,其他时候使用DFS;
(4)DFS 是线,BFS 是面;相当于 DFS 是单打独斗,BFS 是集体行动;
1、BFS(广度优先搜索)
BFS 主要解决最短路径问题,BFS 又分为传统 BFS 和双向 BFS;传统 BFS 是从起点开始扩散,遇到终点时停止;双向 BFS是从起点和终点同时开始扩散,且当两边有交集时停止;虽然二者的最坏时间复杂度相同,但是实际上双向 BFS会较快一些;二者空间复杂度相同;
只要涉及暴力穷举的问题,BFS 都可以使用,而且可以更快地找到答案;在使用 BFS 框架时,如果遇到二维数组问题,一般都会转化为一维数组处理,因为二维数组套用 BFS 框架比较麻烦且效率低;如滑动拼图问题, labuladong 的算法小抄 P311 ;
注:使用双向 BFS 的前提是必须知道终点在哪里;
下面举例说明;
(1)BFS 求二叉树的最小高度
(2)BFS 求解开密码锁的最少次数
注:在双向 BFS 中,如果每次选择较小的集合进行扩散,占用的空间增长速度就会慢一些,且效率会高一些;即在 while 循环开始时做一个交换,找出较小的集合;
2、DFS(深度优先搜索)
DFS 主要解决最短路径以外的搜索问题(例如涉及排序的相关问题);深度优先搜索主要包括:先序遍历、中序遍历和后续遍历;
(1)先序遍历
二、查找问题
1、已知数组—无序状态
优先考虑:unordered_set、unordered_map 容器
原因1:两者的实现都是基于哈希表,其在插入和查找问题上时间复杂度很低,且高效,代价是消耗较多的内存;
原因2:两者都有 find() 内置函数,查找起来比较方便;
2、已知数组—有序状态
优先考虑:二分查找,套用模板;
注:在实现二分查找的过程中也可以考虑使用 unordered_set、unordered_map 容器;
二分查找模板如下:
注:模板参考 labuladong 的算法小抄 P83
三、回溯算法
解决回溯问题,实际上就是一个决策树的遍历问题,所以解决回溯问题使用的方法是二叉树的先序遍历,只不过二叉树变成了多叉树;且回溯算法就是纯暴力穷举,复杂度一般都很高;
下面使用 Leetcode 例题说明;
回溯方法的框架见: labuladong 的算法小抄 P43
注:总结仅仅是为了自己在刷题后期复习起来比较方便,持续更新中;