本题是Topological Sort的一个典型应用,要通过本题学会Topological Sort!

    1. 构建有向图List<List<Integer>>
    2. 运用DFS按顺序访问所有点
      1. 初始化一维数组: visited0: 未访问;1: 正在访问,2: 已访问
        1. 如果DFS过程中遇到已访问的点,跳过
        2. 如果遇到正在访问的点,说明出现了cycle,无法完成courses
        3. 成功访问了某个点的所有neighbors的时候,可以将本点的状态由 正在访问 -> 已访问
        4. 访问过的点的倒序,其实就是需要上课的真实顺序,也是Topological Sort的核心
    • 时间复杂度:
      • 每个点只访问一遍
      • 207. Course Schedule[没有解出] - 图1
    • 空间复杂度:207. Course Schedule[没有解出] - 图2

    代码:

    1. class Solution {
    2. public boolean canFinish(int numCourses, int[][] prerequisites) {
    3. List<List<Integer>> graph = new ArrayList<>();
    4. for (int i = 0; i < numCourses; ++i) {
    5. graph.add(new ArrayList<>());
    6. }
    7. for (int[] prerequisite : prerequisites) {
    8. graph.get(prerequisite[1]).add(prerequisite[0]);
    9. }
    10. int[] visited = new int[numCourses]; // 0: unvisited, 1: visiting, 2: visited
    11. for (int i = 0; i < numCourses; ++i) {
    12. if (visited[i] == 2) {
    13. continue;
    14. }
    15. if (dfs(visited, i, graph)) {
    16. return false;
    17. }
    18. }
    19. return true;
    20. }
    21. // return true if there is a cycle
    22. private boolean dfs(int[] visited, int course, List<List<Integer>> graph) {
    23. if (visited[course] == 1) {
    24. return true; // find cycle
    25. }
    26. visited[course] = 1;
    27. for (Integer next : graph.get(course)) {
    28. if (visited[next] == 2) {
    29. continue;
    30. }
    31. if (dfs(visited, next, graph)) {
    32. return true;
    33. }
    34. }
    35. visited[course] = 2;
    36. return false;
    37. }
    38. }