微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

LeetCode 0207 Course Schedule

原题传送门

1. 题目描述

2. Solution 1

1、思路分析
This problem is equivalent to detecting a cycle in the directed graph represented by prerequisites. Both BFS and DFS can be used to solve it using the idea of topological sort. Since pair<int, int> is inconvenient for implementing graph algorithms, we first transform it to the adjacency-list representation. If course u is a prerequisite of course v, then the adjacency list of u will contain v.

BFS
BFS uses the indegrees of each node. We will first try to find a node with 0 indegree. If we fail to do so, there must be a cycle in the graph and we return false. Otherwise we set its indegree to be -1 to prevent from visiting it again and reduce the indegrees of its neighbors by 1. This process will be repeated for n (number of nodes) times.

2、代码实现

package Q0299.Q0207CourseSchedule;

import java.util.ArrayList;
import java.util.List;

/*
    This problem is equivalent to detecting a cycle in the directed graph represented by prerequisites. Both BFS and
    DFS can be used to solve it using the idea of topological sort. Since pair<int, int> is inconvenient for
    implementing graph algorithms, we first transform it to the adjacency-list representation. If course u is a
    prerequisite of course v, then the adjacency list of u will contain v.

    BFS
    BFS uses the indegrees of each node. We will first try to find a node with 0 indegree. If we fail to do so, there
    must be a cycle in the graph and we return false. Otherwise we set its indegree to be -1 to prevent from visiting
    it again and reduce the indegrees of its neighbors by 1. This process will be repeated for n (number of nodes) times.
 */
public class Solution1 {

    public boolean canFinish(int numCourses, int[][] prerequisites) {
        List<List<Integer>> g = buildGraph(numCourses, prerequisites);
        List<Integer> degrees = computerIndegrees(g);
        for (int i = 0; i < numCourses; i++) {
            int j = 0;
            for (; j < numCourses; j++)
                if (degrees.get(j) == 0) break; // 找到了入度为0的顶点,作为遍历的起点
            if (j == numCourses) return false;  // 没有找到入度为0的顶点
            degrees.set(j, degrees.get(j) - 1);
            for (int v : g.get(j)) degrees.set(v, degrees.get(v) - 1);
        }
        return true;
    }

    /*
        [1, 0] To take course 1 you should have finished course 0, 0 -> 1.
        对于 p=prerequisites[i] 中的数对,边的方向是 p[1] -> p[0]
        使用邻接表的方式存储图
     */
    private List<List<Integer>> buildGraph(int numCourses, int[][] prerequisites) {
        List<List<Integer>> g = new ArrayList<>();
        for (int i = 0; i < numCourses; i++) g.add(new ArrayList<>());
        for (int[] p : prerequisites)
            g.get(p[1]).add(p[0]); // p[1] -> p[0]
        return g;
    }

    // 计算上面构建的图结构中,每个点的入度
    List<Integer> computerIndegrees(List<List<Integer>> g) {
        List<Integer> degrees = new ArrayList<>();
        for (int i = 0; i < g.size(); i++) degrees.add(0);
        for (List<Integer> adj : g) {
            for (int v : adj) {
                degrees.set(v, degrees.get(v) + 1);
            }
        }
        return degrees;
    }
}

3、复杂度分析
时间复杂度: O(m+n)
空间复杂度: O(m+n)

3. Solution 2

1、思路分析
DFS
For DFS, in each visit, we start from a node and keep visiting its neighbors, if at a time we return to a visited node, there is a cycle. Otherwise, start again from another unvisited node and repeat this process. We use todo and done for nodes to visit and visited nodes.

2、代码实现

package Q0299.Q0207CourseSchedule;

import java.util.ArrayList;
import java.util.List;

/*
    DFS
    For DFS, in each visit, we start from a node and keep visiting its neighbors, if at a time we return to a visited
    node, there is a cycle. Otherwise, start again from another unvisited node and repeat this process. We use todo
    and done for nodes to visit and visited nodes.
 */
public class Solution2 {
    public boolean canFinish(int numCourses, int[][] prerequisites) {
        List<List<Integer>> g = buildGraph(numCourses, prerequisites);
        boolean[] todo = new boolean[numCourses], done = new boolean[numCourses];
        for (int i = 0; i < numCourses; i++) {
            if (!done[i] && !acylic(g, todo, done, i)) return false;
        }
        return true;
    }

    private boolean acylic(List<List<Integer>> g, boolean[] todo, boolean[] done, int node) {
        if (todo[node]) return false;
        if (done[node]) return true;

        todo[node] = done[node] = true;
        for (int v : g.get(node)) {
            if (!acylic(g, todo, done, v)) return false;
        }
        todo[node] = false;
        return true;
    }

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

3、复杂度分析
时间复杂度: O(m+n)
空间复杂度: O(m+n)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐