算法小白,2024年2月21日,开始挑战在掘金发布“每日”系列。 (节假日可能会出门所以不算) 涉及到算法,type challenge 等,感兴趣的小伙伴可以持续关注督促互勉 🚀🚀🚀
算法
Dijkstra 算法求图中两点的最短距离
题意分析
找到图中某个起点到某个终点的最短路径 (路径权重为正数)
思路
- 统计到达所有节点的最短路径,初始化为无穷大
- 统计访问过的节点,初始化为空
- 设置起点的最短路径为0
- 从起点开始,作为当前节点,遍历当前节点的相邻节点
- 当前相邻节点的最短路径为当前节点到当前相邻节点的路径 + 当前节点的最短路径
- 对比当前相邻节点的最短路径和计算值,取最小值,更新当前相邻节点最短路径
- 到下一次迭代,找到未访问中最短路径的点,开始下一次迭代
- 直到迭代完成找到最终的目标点
以下图为例:
distances = {1: 0, 2: Infinity, 3: Infinity, 4: Infinity}
起点为 1,终点为 4
1 到自己的最短距离为 0
遍历相邻节点,到 2 节点最短为 1,到 3 节点最短为 4
标记 1 为已经遍历, 第一次遍历结束,此时:
distances = {1: 0, 2: 1, 3: 4, 4: Infinity}
visited = [1]
=============
第二次循环,因为 1 已经被记录过,继续判断其他节点
最短距离的节点是 2 号节点,因此此次节点更新为 2
遍历相邻节点,到 3 号节点距离为 2,3号节点存在值,为4,因此更新最短距离
到 4 号节点距离为 4,4号节点默认值为 Infinity,因此更新最短距离
=============
第三次循环,1,2 已经被记录,3号节点最小距离为 3,4号节点为4
最短距离节点是 3,因此此次节点更新为 3
遍历 3 号节点的相邻节点,发现无法获得相邻节点的更小路径,不更新
第四次循环,只剩下 4 号点位,到达终点,结束
代码实现
const dijkstra = (graph, start, end) => {
let distances = {}
let visited = {}
// 初始化所有的节点最短距离
// 初始化访问过的节点
for (let node in graph){
distance[node] = Infinity
visited[node] = false
}
// 初始化起点
distance[start] = 0
// 每次迭代找到未访问过节点的距离最短节点作为开始节点
while(true) {
let minNode = null
for (let node in graph) {
if (!visited[node] && (minNode === null || distances[minNode] < distances[node])) {
minNode = node
}
}
// 没有节点或者访问完毕
if (minNode === null) break
// 遍历最近距离节点的附近节点
// 计算距离为最近节点的距离+最近节点到相邻节点之间的距离
// 如果这个距离小于记录中相邻节点的距离,说明还未更新或是找到了更短的距离
// 更新最短的距离,并保存这个节点的父节点
// 最小节点设置为已经访问过
for (const neighbor of graph[minNode]) {
let distance = distances[minNode] + graph[minNode][neighbor]
if (distance < distances[neighbor]) {
distances[neighbor] = distance
}
}
visited[minNode] = true
}
reutrn distances[end]
}
TypeChallenge
实现类型 IsNever<T> ,判断类型是否是 never
type todo = never
type preview = IsNever<todo> // true
思路
- 无法直接判断 never
- 可以转换成元组,再进行判断
解题
type IsNever = [T] extends [never] ? true : false