DFS
通过一些leetcode上面的题目, 总结出以下类型的题目;
- 树先序遍历
- DFS + 回溯
- DFS + 记忆化
- DFS + 减枝
- DFS 求最短路
- DFS 求联通块儿
先序遍历
过于简单, 看看数据结构都能懂的。
题目
DFS + 回溯
比较典型的问题是 迷宫
, 八皇后
等问题, 也比较简单。
当此题如果是判断某种情况存不存在, 则判断到存在的时候立马停止掉后续的所有DFS。
题目
DFS + 记忆化
DFS
过程当中同一个 节点的 状态可以多次进入, 而多次进入的需要求得结果均可使用第一次求得的结果, 这样能节省大量的时间。
模板
T dfs(...)
{
if 子节点已经记载:
求得当前顶点所对应的值
else
dfs(子节点)
再求得当前顶点所对应的值
//此处记载当前顶点对应的值。
}
题目
给定一个整数矩阵,找出最长递增路径的长度。
对于每个单元格,你可以往上,下,左,右四个方向移动。 你不能在对角线方向上移动或移动到边界外(即不允许环绕)。
输入: nums =
[
[9,9,4],
[6,6,8],
[2,1,1]
]
输出: 4
解释: 最长递增路径为 [1, 2, 6, 9]。
分析
当DFS过程当中, 记录下当前DFS过程当中每个顶点的最长上升长度, 当其余DFS过程再次进入这些顶点的时候, 能够直接使用而不用在递归了。
DFS + 减枝
根据先前DFS路径当中求得的某些结果, 判断当前DFS是否继续进行下去。
DFS求最短路径
列出如下三种情况求一个顶点到剩余所有顶点的最短距离
, 求一个顶点最多只能经过K条边到剩余顶点的最短距离
, 求一个顶点最多只能经过K条边到指定顶点的最短距离
, 并作出 减枝条件的 对比。
题目1
编号从1-n的一个有向图, 求编号为1的顶点到其他顶点之间的最短距离。
分析
当DFS
过程当中发生一个顶点二次进入的时候, 减枝方法为: 只需判断 先前DFS得出的 1
到 当前顶点距离, 和 当前DFS得出的 1
到 当前顶点的距离即可, 前者大, 则继续DFS, 后者大, 则终止当前DFS。
题目2
顶点编号从1-n的有向图, 求出顶点1, 经过k条边所能到达的顶点的最短距离。
分析
当DFS
过程当中发生一个顶点的二次进入的时候, 不能再使用题目一当中的减枝条件了, 因为即使 1
到 当前顶点的距离比先前DFS计算的大, 但是可能 此 DFS 到当前顶点的经过的边数少, 能到达先前DFS过程中未能达到的顶点, 因此减枝条件为: 如果到达此顶点时经过的边数少于先前DFS到达此顶点时的边数, 则继续DFS, 反之 则 需要比较两次的DFS的距离, 此次距离小才能继续DFS, 否则减枝。
题目3
有 n 个城市通过 m 个航班连接。每个航班都从城市 u 开始,以价格 w 抵达 v。
现在给定所有的城市和航班,以及出发城市 src 和目的地 dst,你的任务是找到从 src 到 dst 最多经过 k 站中转的最便宜的价格。 如果没有这样的路线,则输出 -1。
示例 1:
输入:
n = 3, edges = [[0,1,100],[1,2,100],[0,2,500]]
src = 0, dst = 2, k = 1
输出: 200
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/
cheapest-flights-within-k-stops
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
分析
当有K
约束时候, 需要限定DFS的路径(深度) 不能超过K的同时, 减枝方法应该修改为: 如果当前路径长度已经大于先前 DFS 累计的长度, 则终止此条DFS路径(减枝非必须, 为了不超时)。