激动,终于最后一天了。
基础
刷题
- 小明逛公园
Floyd算法 (弗洛伊德算法)
Floyd算法主要是动态规划的思路。这里使用动规五部曲:
- 确定dp数组
// 使用邻接矩阵存储 grid = make([][]int, n+1) // dp数组是一个三维数组,在grid上加一个维度k,grid[k][i][j], k是起点为i,终点为j, // 中间可以经过[1-k] 中转的路径中的最短路径。 dp = make([][][]int, n+1)
//当然dp数组是可以压缩的 dp = make([][]int, n+1)
- 确定dp数组递推公式
dp[k][i][j] = min(dp[k-1][i][j], dp[k-1][i][k], dp[k-1][k][j])
// 压缩 dp[i][j] = min(dp[i][j], dp[i][k] + dp[k][j])
- 确定dp数组初始化
先存储dp[0], 也就是输入的邻接矩阵,其他初始化为math.MaxInt32
- 确定dp数组遍历顺序
k 从1到n
- 打印dp数组
- 骑士的攻击
本题主要是使用A算法,是广搜算法的优化版本,主要是通过G,H,F三个参数来寻找 F 最短的那一个(使用堆优化队列),F是A算法中,对最优节点的计算方法,F= G+H
- G = 从起点到该节点路径消耗
- H = 该节点到终点的预估消耗
Astar 是一种 广搜的改良版。 有的是 Astar是 dijkstra 的改良版。
其实只是场景不同而已 我们在搜索最短路的时候, 如果是无权图(边的权值都是1) 那就用广搜,代码简洁,时间效率和 dijkstra 差不多 (具体要取决于图的稠密)
如果是有权图(边有不同的权值),优先考虑 dijkstra。
总结
最短路径
最短路径的算法总结,dijkstra,dijkstra堆优化版本,bellman_ford, SPFA,floyd算法,A star属于启发式搜索,与前面几种算法不是同一种类型。
www.programmercarl.com/kamacoder/%…
如果遇到单源且边为正数,直接Dijkstra。
如果遇到单源边可为负数,直接 Bellman-Ford,同样 SPFA 还是 Bellman-Ford 取决于图的稠密度。
如果有负权回路,优先 Bellman-Ford, 如果是有限节点最短路 也优先 Bellman-Ford,理由是写代码比较方便。
如果是遇到多源点求最短路,直接 Floyd。
并查集
- 并查集解决的问题
两个节点在不在同一个集合,如何将2两个节点放入同一个集合
- 并查集原理以及代码实现
- 并查集写法的常见误区
在join的时候,不是合并的根结点
最小生成树
两个算法: prim算法 和 kruskal 算法
Prim算法三部曲:
- 寻找距离最小生成树最近的节点
- 加入最小生成树
- 更新非最小生成树节点 到最小生成树的距离(更新minDist数组)
kruskal 算法:
- 把所有的边排序,找到权值最小的那条边,加入到最小生成树中
- 遍历未加入到最小生成树的边,使用并查集
- 如果边左右两个节点都在最小生成树中,那么就形成了环
- 如果边左右两个节点不在一个集合,加入最小生成树
拓扑排序
给出一个 有向图,把这个有向图转成线性的排序 就叫拓扑排序
对于有向图,可以把a指向b,看作b依赖于a,需要执行b,必须要先完成a
拓扑排序的一些应用场景,例如:大学排课,文件下载依赖 等等。
解题两个步骤:
- 找到入度为0的节点,加入结果集
- 删掉该节点为头的边,再次寻找入度为0的节点