zoukankan      html  css  js  c++  java
  • LeetCode——课程安排 IV

    Q:你总共需要上 n 门课,课程编号依次为 0 到 n-1 。
    有的课会有直接的先修课程,比如如果想上课程 0 ,你必须先上课程 1 ,那么会以 [1,0] 数对的形式给出先修课程数对。
    给你课程总数 n 和一个直接先修课程数对列表 prerequisite 和一个查询对列表 queries 。
    对于每个查询对 queries[i] ,请判断 queries[i][0] 是否是 queries[i][1] 的先修课程。
    请返回一个布尔值列表,列表中每个元素依次分别对应 queries 每个查询对的判断结果。
    注意:如果课程 a 是课程 b 的先修课程且课程 b 是课程 c 的先修课程,那么课程 a 也是课程 c 的先修课程。


    示例 2:
    输入:n = 2, prerequisites = [], queries = [[1,0],[0,1]]
    输出:[false,false]
    解释:没有先修课程对,所以每门课程之间是独立的。

    示例 4:
    输入:n = 3, prerequisites = [[1,0],[2,0]], queries = [[0,1],[2,0]]
    输出:[false,true]
    示例 5:
    输入:n = 5, prerequisites = [[0,1],[1,2],[2,3],[3,4]], queries = [[0,4],[4,0],[1,3],[3,0]]
    输出:[true,false,true,false]
     
    提示:
    2 <= n <= 100
    0 <= prerequisite.length <= (n * (n - 1) / 2)
    0 <= prerequisite[i][0], prerequisite[i][1] < n
    prerequisite[i][0] != prerequisite[i][1]
    先修课程图中没有环。
    先修课程图中没有重复的边。
    1 <= queries.length <= 10^4
    queries[i][0] != queries[i][1]

    A:

    1. DFS+Memo
        public List<Boolean> checkIfPrerequisite(int n, int[][] prerequisites, int[][] queries) {
            Map<Integer, Set<Integer>> graph = new HashMap<>();
            for (int[] pre : prerequisites) {
                Set<Integer> set = graph.getOrDefault(pre[0], new HashSet<>());
                set.add(pre[1]);
                graph.put(pre[0], set);
            }
            List<Boolean> ret = new ArrayList<>();
            boolean[][] isCalculated = new boolean[n][n];//一个用来记录计没计算过
            boolean[][] cache = new boolean[n][n];//一个用来记录计算后的结果
            for (int[] query : queries) {
                ret.add(dfs(query[0], query[1], graph, isCalculated, cache));
            }
            return ret;
        }
    
        private Boolean dfs(int start, int target, Map<Integer, Set<Integer>> graph, boolean[][] isCalculated, boolean[][] cache) {
            if (isCalculated[start][target])
                return cache[start][target];
            isCalculated[start][target] = true;
            if (start == target)
                return cache[start][target] = true;
            if (!graph.containsKey(start)) {
                return cache[start][target] = false;
            }
            for (int ch : graph.get(start)) {
                isCalculated[start][ch] = true;
                cache[start][ch] = true;
                if(dfs(ch, target, graph, isCalculated, cache))
                    return cache[start][target] = true;
            }
            return cache[start][target] = false;
        }
    
    1. 有DFS,就有BFS,同样用一个memo记录是否访问过
        public List<Boolean> checkIfPrerequisite(int n, int[][] prerequisites, int[][] queries) {
            Map<Integer, Set<Integer>> graph = new HashMap<>();
            for (int[] pre : prerequisites) {
                Set<Integer> set = graph.getOrDefault(pre[0], new HashSet<>());
                set.add(pre[1]);
                graph.put(pre[0], set);
            }
            List<Boolean> ret = new ArrayList<>();
            for (int[] query : queries) {
                ret.add(bfs(n, query[0], query[1], graph));
            }
            return ret;
        }
    
        private Boolean bfs(int n, int start, int target, Map<Integer, Set<Integer>> graph) {
            if (start == target || (graph.containsKey(start) && graph.get(start).contains(target)))
                return true;
            if (!graph.containsKey(start)) {
                return false;
            }
            boolean[] visited = new boolean[n];
            Arrays.fill(visited, false);
            Queue<Integer> q = new LinkedList<>();
            q.add(start);
            while (!q.isEmpty()) {
                int curr = q.poll();
                Set<Integer> set = graph.getOrDefault(start, new HashSet<>());
                set.add(curr);
                graph.put(start, set);
                if(curr == target)
                    return true;
                else{
                    if(!visited[curr]){
                        visited[curr] = true;
                        if(graph.containsKey(curr)){
                            Set<Integer> temp = graph.get(curr);
                            q.addAll(temp);
                        }
                    }
                }
            }
            return false;
        }
    
    1. floyd-warshall算法(该算法其实是用来求最短路的),又名打表法:
      有向图的传递闭包:给定有向图G=(V,E),我们希望判断对于所有结点对i,j,图G是否包含一条对节点i,j的路径。
      传递闭包具有传递性,即如果i->j,j->k,那么i->k。具体来说,对于边(u,v),枚举所有形如(j,u)的边,若(j,u)存在边,即j->u,那么由于u->v,那么j->v。
      用于该题,即对于每个prerequisite,i->l 那么 i->l->r 即i->1;r->j 那么 l->r->j 即l->j
        public List<Boolean> checkIfPrerequisite(int n, int[][] prerequisites, int[][] queries) {
            boolean[][] arr = new boolean[n][n];
            for (int[] p : prerequisites) {
                int l = p[0], r = p[1];
                arr[l][r] = true;
                for (int i = 0; i < n; i++) {
                    if (arr[i][l])
                        arr[i][r] = true;
                }
                for (int j = 0; j < n; j++) {
                    if (arr[r][j])
                        arr[l][j] = true;
                }
            }
            List<Boolean> res = new ArrayList<>();
            for (int[] q : queries) {
                res.add(arr[q[0]][q[1]]);
            }
            return res;
        }
    
  • 相关阅读:
    java stackoverflowerror与outofmemoryerror区别
    JVM参数笔记
    记录一次JVM配置优化的案例
    JVM相关内容简介(转)
    Spring boot中的定时任务(计划任务)
    netty学习:UDP服务器与Spring整合(2)
    netty学习:UDP服务器与Spring整合
    maven 纯注解一步一步搭建Spring Mvc项目(入门)
    将class类对象转化成json的数据格式
    Spring五个事务隔离级别和七个事务传播行为
  • 原文地址:https://www.cnblogs.com/xym4869/p/13459286.html
Copyright © 2011-2022 走看看