挑战 - 每日系列(Algorithm + TypeChallenge)

109 阅读3分钟

算法小白,2024年2月21日,开始挑战在掘金发布“每日”系列。 (节假日可能会出门所以不算) 涉及到算法,type challenge 等,感兴趣的小伙伴可以持续关注督促互勉 🚀🚀🚀

算法

Dijkstra 算法求图中两点的最短距离

题意分析

找到图中某个起点到某个终点的最短路径 (路径权重为正数)

思路

  • 统计到达所有节点的最短路径,初始化为无穷大
  • 统计访问过的节点,初始化为空
  • 设置起点的最短路径为0
  • 从起点开始,作为当前节点,遍历当前节点的相邻节点
  • 当前相邻节点的最短路径为当前节点到当前相邻节点的路径 + 当前节点的最短路径
  • 对比当前相邻节点的最短路径和计算值,取最小值,更新当前相邻节点最短路径
  • 到下一次迭代,找到未访问中最短路径的点,开始下一次迭代
  • 直到迭代完成找到最终的目标点

以下图为例:

image.png

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