Woodyiiiiiii / LeetCode

My private record of Leetcode solution

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Leetcode 2642. Design Graph With Shortest Path Calculator

Woodyiiiiiii opened this issue · comments

模版题:求有向权值图中某个点到另一个点的最短路径。

1、Dijkstra

第一种方法就是用堆优化。用dist一维数组表示start起点到i点的最短距离,用最小堆记录下一个结点和权值:

class Graph {

    int n;
    Map<Integer, List<int[]>> adjList;

    public Graph(int n, int[][] edges) {
        this.n = n;
        adjList = new HashMap<>();
        for (int i = 0; i < n; i++) {
            adjList.put(i, new ArrayList<>());
        }
        for (int[] edge : edges) {
            int u = edge[0], v = edge[1], w = edge[2];
            adjList.get(u).add(new int[]{v, w});
        }
    }

    public void addEdge(int[] edge) {
        int u = edge[0], v = edge[1], w = edge[2];
        adjList.get(u).add(new int[]{v, w});
    }

    public int shortestPath(int node1, int node2) {
        int[] dist = new int[n];
        Arrays.fill(dist, Integer.MAX_VALUE);
        dist[node1] = 0;
        PriorityQueue<int[]> pq = new PriorityQueue<>(Comparator.comparingInt(a -> a[1]));
        pq.add(new int[]{node1, 0});
        while (!pq.isEmpty()) {
            int[] curr = pq.poll();
            int u = curr[0], d = curr[1];
            if (u == node2) {
                return dist[u];
            }
            for (int[] edge : adjList.get(u)) {
                int v = edge[0], w = edge[1];
                if (dist[v] > dist[u] + w) {
                    dist[v] = dist[u] + w;
                    pq.add(new int[]{v, dist[v]});
                }
            }
        }
        return -1;
    }
}

/**
 * Your Graph object will be instantiated and called as such:
 * Graph obj = new Graph(n, edges);
 * obj.addEdge(edge);
 * int param_2 = obj.shortestPath(node1,node2);
 */

另一种Dijkstra是设立访问数组,遍历所有结点,寻找最小的未被访问的dist,然后找到下一个结点。可以用数学归纳法证明遍历过的结点已经是最小值了。

class Graph {

    int n;
    Map<Integer, List<int[]>> adjList;

    public Graph(int n, int[][] edges) {
        this.n = n;
        adjList = new HashMap<>();
        for (int i = 0; i < n; i++) {
            adjList.put(i, new ArrayList<>());
        }
        for (int[] edge : edges) {
            int u = edge[0], v = edge[1], w = edge[2];
            adjList.get(u).add(new int[]{v, w});
        }
    }

    public void addEdge(int[] edge) {
        int u = edge[0], v = edge[1], w = edge[2];
        adjList.get(u).add(new int[]{v, w});
    }

    public int shortestPath(int node1, int node2) {
        int[] dist = new int[n];
        Arrays.fill(dist, Integer.MAX_VALUE);
        dist[node1] = 0;
        boolean[] v = new boolean[n];
        for (;;) {
            int x = -1;
            for (int i = 0; i < n; ++i) {
                if (!v[i] && (x < 0 || dist[i] < dist[x])) {
                    x = i;
                }
            }
            if (x < 0 || dist[x] == Integer.MAX_VALUE) {
                return -1;
            }
            if (x == node2) {
                return dist[node2];
            }
            v[x] = true;
            if (!adjList.containsKey(x)) {
                continue;
            }
            for (int[] next : adjList.get(x)) {
                dist[next[0]] = Math.min(dist[next[0]], dist[x] + next[1]);
            }
        }
    }
}

/**
 * Your Graph object will be instantiated and called as such:
 * Graph obj = new Graph(n, edges);
 * obj.addEdge(edge);
 * int param_2 = obj.shortestPath(node1,node2);
 */

时间复杂度O(qn^2)。

2、floyd
看详解。