最短路径 dijkstra算法 floyd算法

dijkstra

算法的基本思想是贪⼼,每次都遍历所有邻居,并从中找到距离最⼩的,
本质上是⼀种⼴度优先遍历。这⾥我们借助堆这种数据结构。

题目
在这里插入图片描述

class Solution {
    public int networkDelayTime(int[][] times, int n, int k) {
        List<int[]>[] graph = buildGraph(times, n);
        int[] minDistance = dijkstra(graph, k);
        int res = 0;
        for(int i = 1; i < minDistance.length; i++){
            if(minDistance[i] == Integer.MAX_VALUE){
                return -1;
            }
            res = Math.max(res, minDistance[i]);
        }
        return res;


    }

    public List<int[]>[] buildGraph(int[][] times, int n){
        List<int[]>[] graph = new ArrayList[n+1];
        for(int i = 0; i <= n; i++){
            graph[i] = new ArrayList<>();
        }
        for(int[] time : times){
            int from = time[0];
            int to = time[1];
            int weight = time[2];
            graph[from].add(new int[]{to,weight});
        }
        return graph;
    }

    public int[] dijkstra(List<int[]>[] graph, int start){
        Queue<State> pq = new PriorityQueue<>((o1,o2) -> {
            return Integer.compare(o1.disTo, o2.disTo);
        });
        //记录最小距离
        int[] minDistance = new int[graph.length];
        Arrays.fill(minDistance, Integer.MAX_VALUE);
        minDistance[start] = 0;
        //开启dijkstra算法核心
        pq.offer(new State(start, 0));
        while(!pq.isEmpty()){
            State node = pq.poll();
            if(node.disTo > minDistance[node.id]){
                continue;
            }
            for(int[] nextNode : graph[node.id]){
                int nextId = nextNode[0];
                int disToNext = nextNode[1] + node.disTo;
                if(disToNext >= minDistance[nextId]){
                    continue;
                }
                pq.offer(new State(nextId, disToNext));
                minDistance[nextId] = disToNext; 
            }
        }
        return minDistance;
    }


}

class State{
    public int id;
    public int disTo;
    State(int id, int disTo){
        this.id = id;
        this.disTo = disTo;
    }
}

floyd

floyed 算法
判断从i到j 是否有路径。
判断从i 途径 mid 到j是否有路径。
查询从任意的i 到任意的j 是否有路径。

i 到 j 的最短路径 = i 到 k 的最短路径 + k 到 j 的最短路径的最小值
floyd_warshall 算法由于使⽤了动态规划的思想而不是贪心,因此其可以处理负权重的情况

题目
在这里插入图片描述

class Solution {
    public List<Boolean> checkIfPrerequisite(int numCourses, int[][] prerequisites, int[][] queries) {
        boolean[][] dp = new boolean[numCourses][numCourses];
        List<Boolean> res = new ArrayList<>();
        for(int[] require : prerequisites){
            dp[require[0]][require[1]] = true;
        }
        for(int mid = 0; mid < numCourses; mid++){
            for(int i = 0; i < numCourses; i++){
                for(int j = 0; j < numCourses; j++){
                    dp[i][j] = dp[i][j] || (dp[i][mid] && dp[mid][j]);
                }
            }
        }
        for(int i = 0;i < queries.length; i++){
            if(dp[queries[i][0]][queries[i][1]]){
                res.add(true);
            }else{
                res.add(false);
            }
        }
        return res;
    }
}

在这里插入图片描述

因为没环,直接上dfs,都不用统计visited(map也帮忙记录了visited情况。注意使用后序遍历,不然超时,注意避免重叠子问题的计算。

class Solution {
    public List<Boolean> checkIfPrerequisite(int numCourses, int[][] prerequisites, int[][] queries) {
        List<Integer>[] graph = buildGraph(prerequisites, numCourses);
        Map<Integer,Set<Integer>> map = new HashMap<>();
        List<Boolean> res = new ArrayList<>();
        for(int[] query : queries){
            if(!map.containsKey(query[0])){
                Set<Integer> set = new HashSet<>();
                dfs(graph, map, query[0]);
            }
            if(map.get(query[0]).contains(query[1])){
                res.add(true);
            }else{
                res.add(false);
            }
        }
        return res;
    }

    public List<Integer>[] buildGraph(int[][] prerequisites, int numCourses){
        List<Integer>[] graph = new ArrayList[numCourses];
        for(int i = 0; i < numCourses; i++){
            graph[i] = new ArrayList<>();
        }
        for(int[] pre : prerequisites){
            graph[pre[0]].add(pre[1]);
        }
        return graph;
    }

    public Set<Integer> dfs(List<Integer>[] graph, Map<Integer,Set<Integer>> map,int course){
        Set<Integer> set = new HashSet();
        for(int nextCourse : graph[course]){
            if(map.containsKey(nextCourse)){
                set.add(nextCourse);
                set.addAll(map.get(nextCourse));
            }else{
                set.add(nextCourse);
                set.addAll(dfs(graph, map, nextCourse));
            }
        }
        map.put(course, set);
        return set;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值