二维矩阵/邻接表
对于一般的DFS问题,其相邻的边代表了不同的搜索方向,有向图一般不会陷入重复搜索的死循环,因此不需要标记已访问节点的seen矩阵,比如二叉树问题,797. 所有可能的路径;而无向图则需要定义的一个标记已访问节点的seen矩阵。
DFS 一般可以用来确定连通域(岛屿等), BFS可以用来查找最短路径长度等。
DFS + BFS 。 DFS找到其中的一个岛屿,然后利用BFS逐步往外扩展,直到碰到第二个岛屿。这里需要注意的是
DFS+剪枝
染色问题
有两种颜色,红色和蓝色。不喜欢的两个元素应该图不同的颜色。 红色为1, 蓝色为-1。初始时节点颜色都标记为0, 非零则表示已经对该节点已经相邻的节点完成染色。
这是一个环检测问题。利用染色的思想判断从某个节点的任意邻居出发是否有环。只有当所有的邻居都不能进入环时,其才可能达到安全状态。0为初始状态,1为安全状态,-1为不安全状态。
从一个节点出发如果能达到自己或者其他不安全的节点,则该节点也是不安全,因此对每个节点而言, 我们先将其标记为不安全状态,待确保其所有相邻几点都是安全节点时再将其标记为安全状态。
单源最短路径
连通域问题:
一个城市从直接相邻的城市出发用 DFS 查找间接相邻的城市。每个城市只能属于一个省份。
属于同一个用户名的邮箱有一条边相连, 因此账户合并问题将转化成连通域问题。
路径问题
一维序列
自顶向下和自底向上均可,但是无论哪种方式,set 都可以辅助进行去重功能。
自底向上:先得到子序列的递增序列,然后处理加入当前元素之后的新的递增序列。
自顶向下:我们可以用一个vector表示待加入结果中的候选序列,从前往后处理,那么对于一个新元素,如果满足递增条件,那么它有两种选择,要么加入递增序列,要么不加入。
自顶向下,对每个元素有两种选择,要么加要么减。 但是这种方法时间复杂度比较高。这其实是典型的背包为题。可以借助动态规划解决。
先找出每个位置能够放置数字集合,然后从前往后用 dfs 逐个位置放置不同的数字求求解满足的一个排列,注意同一个排列中,一个数字只能出现依次。
自底向上
先求字串的字母组合,再枚举添加当前字符之后的结果。
自顶向下
利用快慢指针确定根节点的位置,然后分别递归处理左右子树。
依赖关系形成图,有环则代表循环依赖,无法完成课程。利用邻接表逐个节点自顶向下判断是否有环。
正方形的四条边相当于四个小盒子,对每根火逐个试探放入其中一个盒子,当把所有火柴都放置完成之后,判断四个盒子的火柴子和是否相等。需要剪枝降低时间复杂度。最大时间复杂度为O(4^N),因为每根火柴有4种放置方法。
小故事:这道题曾花了我一个晚上的时间,一直超时, 开始我给出的方案是从第一根火柴开始搜索能跟该火柴组成边长的其他火柴。从前往后依次累加,当遇到边长的整数倍,就代表找到了一条边的拼法。这样的时间复杂度就变成了O(n*n-1*n-2*....*1) 即O(n的阶乘),现在想想显然是时间复杂度过高,应该及时停止这种算法的考虑。
边界搜索
1) 首先DFS替换边界‘O’以及从此处出发可达的所有‘O’ 为一个特殊符号。然后遍历数组逐个替换其他'O'为‘X’, 最后将特殊符号替换为‘O’.
2) DFS寻找包围域的做法会超时。
从上边界和左边界的点出发,找出所有能到达太平洋的位置,从另外两个边界找出所有能到达大西洋的位置。