zoukankan      html  css  js  c++  java
  • 最短路径(javascript实现)

    743. 网络延迟时间

    有 N 个网络节点,标记为 1 到 N。

    给定一个列表 times,表示信号经过有向边的传递时间。 times[i] = (u, v, w),其中 u 是源节点,v 是目标节点, w 是一个信号从源节点传递到目标节点的时间。

    现在,我们从某个节点 K 发出一个信号。需要多久才能使所有节点都收到信号?如果不能使所有节点收到信号,返回 -1。

    输入:times = [[2,1,1],[2,3,1],[3,4,1]], N = 4, K = 2
    输出:2
    

    深度优先搜索

    以K为起点,深度优先遍历,传入距离值,若距离大于结点已知最小距离则停止深搜,否则更新当前结点

    时间复杂度:O(N^N)

    空间复杂度:O(N+E)

    var networkDelayTime = function (times, N, K) {
        /* 存各条边的信息 */
        const edges = new Map();
        for (let [x, y, val] of times) {
            if (!edges.has(x))
                edges.set(x, [[y, val]]);
            else
                edges.get(x).push([y, val]);
        }
        /* 初始化标记 */
        const vis = new Array(N + 1).fill(false);
        /* 初始化距离 */
        const MAX = Number.MAX_SAFE_INTEGER;
        const dst = new Map();
        for (let i = 1; i <= N; i++) dst.set(i, MAX);
        /* 深搜 */
        function dfs(index, dis) {
            /* 剪枝 */
            if (dst.get(index) < dis) return;
            /* 更新 */
            dst.set(index, dis);
            /* 往下遍历 */
            if (edges.get(index)) {
                for (let [tgt, val] of edges.get(index)) {
                    if (!vis[tgt]) {
                        vis[tgt] = true;
                        dfs(tgt, dis + val);
                        vis[tgt] = false;
                    }
                }
            }
        }
        dfs(K, 0);
        /* 取最大值 */
        let ans = 0;
        for (let v of dst) {
            if (v[1] === MAX) return -1;
            ans = Math.max(ans, v[1]);
        }
        return ans;
    };
    

    Dijkstra解法

    每次找出距离K最近的点minIndex并标记,遍历minIndex相连的所有点tgt,对比K直接到tgt的距离K经过minIndex到达tgt的距离,更新K到tgt的距离两者中的最小值,重复该操作直到所有点均已被标记

    时间复杂度:由于需要N轮更新,每轮遍历N次,所以为O(N^2)

    空间复杂度:O(N+E)

    var networkDelayTime = function (times, N, K) {
        const edges = new Map();
        const dst = new Map();
        /* 转换为起点为索引的边进行存储 */
        for (let [x, y, val] of times) {
            if (!edges.has(x)) {
                edges.set(x, [[y, val]]);
            } else {
                edges.get(x).push([y, val]);
            }
        }
        /* 初始化各点到K的距离 */
        const MAX = Number.MAX_SAFE_INTEGER;
        for (let i = 1; i <= N; i++)  dst.set(i, MAX);
        dst.set(K, 0);
        /* 更新每个结点 */
        const vis = new Array(N + 1).fill(false);
        let minIndex, min;
        for (let k = 1; k <= N; k++) {
            /* 找最小边 */
            minIndex = -1; min = MAX;
            for (let i = 1; i <= N; i++) {
                if (!vis[i] && dst.get(i) < min) {
                    minIndex = i;
                    min = dst.get(i);
                }
            }
            if (minIndex === -1) break;
            /* 标记访问并更新其他相连结点 */
            vis[minIndex] = true;
            if (edges.has(minIndex)) {
                for (let [tgt, val] of edges.get(minIndex)) {
                    // 对比K直接到tgt的距离和经过minIndex到达tgt的距离
                    dst.set(tgt, Math.min(dst.get(tgt), dst.get(minIndex) + val));
                }
            }
        }
        /* 找最大距离 */
        let ans = 0;
        for (let v of dst) {
            //遍历Map的结果是一个数组
            if (v[1] === MAX) return -1;//有不可到达的点
            ans = Math.max(v[1], ans);
        }
        return ans;
    };
    

    SFPA算法

    将被更新的结点放入队列,每次取出队头,遍历与其相关的所有结点,若相关结点值被更新,则放入到队列尾部,以便下次取出来更新后续结点

    时间复杂度:最坏O(V*E),V表示入队次数

    空间复杂度:O(V+E)

    var networkDelayTime = function (times, N, K) {
        /* 存每个节点的所有边 */
        const edges = new Map();
        for (let [x, y, val] of times) {
            if (!edges.has(x)) {
                edges.set(x, [[y, val]]);
            } else {
                edges.get(x).push([y, val]);
            }
        }
        /* 初始化距离 */
        const MAX = Number.MAX_SAFE_INTEGER;
        const dst = new Array(N + 1).fill(MAX);
        dst[K] = 0;
        /* 队列中的元素会引起后续结点更新 */
        const queue = [K];
        while (queue.length) {
            let x = queue.shift();
            // 更新结点
            if (edges.has(x)) {
                for (let [y, val] of edges.get(x)) {
                    if (dst[y] > dst[x] + val) {
                        dst[y] = dst[x] + val;
                        queue.push(y);//存入队列更新y以后的结点
                    }
                }
            }
        }
        /* 找最大值 */
        let ans = 0;
        for (let i = 1; i <= N; i++) {
            ans = Math.max(ans, dst[i]);
        }
        return ans === MAX ? -1 : ans;
    };
    
    
  • 相关阅读:
    Excel技巧大全
    2019年6月27日单词
    HTML5(12) 实时通讯WebSocket
    C#(99):随机数Random
    C#(99):C# 8.0 的新特性( NET Framework 4.8 与 Visual Studio 2019 )
    2019年6月13日单词
    2019年6月5日单词
    2019年5月30日单词
    used to do 与be used to doing /n.
    Json.Net(一)介绍
  • 原文地址:https://www.cnblogs.com/aeipyuan/p/13234524.html
Copyright © 2011-2022 走看看