lotus

贵有恒何必三更眠五更起 最无益只怕一日曝十日寒

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

1. 题目

 

读题

  

考查点

 

2. 解法

思路

这个问题可以用图论的方法来解决,具体思路如下:

将课程和先修课程看作有向图的节点和边,如果要学习课程ai,则必须先学习课程bi,表示为bi->ai。
判断图中是否存在环,如果存在环,则说明有些课程无法完成,返回false;如果不存在环,则说明所有课程都可以完成,返回true。
判断图中是否存在环的方法有多种,例如深度优先搜索(DFS),广度优先搜索(BFS),拓扑排序(Topological Sort)等。
以下是用Java实现的一种基于DFS的解法,代码参考了Leetcode上的一个解答。

 

代码逻辑

这个代码的具体逻辑。😊

  • 首先,我们需要创建一个邻接表来表示图,邻接表是一个列表,每个元素是一个列表,表示一个节点的邻接节点。例如,如果有一条边从节点0指向节点1,那么在邻接表中,第0个元素的列表中就会包含1。
  • 然后,我们需要创建一个访问状态数组来记录每个节点的访问状态,初始值都为0,表示未访问。当我们开始访问一个节点时,我们将其状态改为1,表示正在访问;当我们结束访问一个节点时,我们将其状态改为2,表示已访问。
  • 接下来,我们需要遍历每个节点,对每个节点进行深度优先搜索。深度优先搜索的思想是从一个节点出发,沿着一条路径不断向前探索,直到无法继续或者发现环为止,然后回溯到上一个节点,再沿着另一条路径继续探索,直到遍历完所有的节点为止。
  • 在深度优先搜索的过程中,我们需要判断是否存在环。如果我们发现当前正在访问的节点已经被标记为正在访问,那么说明存在环;如果我们发现当前正在访问的节点已经被标记为已访问,那么说明不存在环;如果我们发现当前正在访问的节点还未被访问过,那么我们就将其标记为正在访问,并且递归地对其邻接节点进行深度优先搜索。
  • 最后,如果在深度优先搜索的过程中没有发现环,那么就返回true,表示所有课程都可以完成;如果发现了环,那么就返回false,表示有些课程无法完成。

 

具体实现

 

class Solution {
    public boolean canFinish(int numCourses, int[][] prerequisites) {
        // 创建邻接表表示图
        List<List<Integer>> adjList = new ArrayList<>();
        for (int i = 0; i < numCourses; i++) {
            adjList.add(new ArrayList<>());
        }
        for (int[] pre : prerequisites) {
            adjList.get(pre[1]).add(pre[0]);
        }
        // 创建访问状态数组,0表示未访问,1表示正在访问,2表示已访问
        int[] visited = new int[numCourses];
        // 遍历每个节点,进行深度优先搜索
        for (int i = 0; i < numCourses; i++) {
            if (dfs(i, adjList, visited)) {
                return false; // 如果发现环,返回false
            }
        }
        return true; // 如果没有发现环,返回true
    }

    // 深度优先搜索函数,返回是否存在环
    private boolean dfs(int cur, List<List<Integer>> adjList, int[] visited) {
        if (visited[cur] == 1) {
            return true; // 如果当前节点正在访问,说明存在环
        }
        if (visited[cur] == 2) {
            return false; // 如果当前节点已访问,说明不存在环
        }
        visited[cur] = 1; // 将当前节点标记为正在访问
        for (int next : adjList.get(cur)) { // 遍历当前节点的邻接节点
            if (dfs(next, adjList, visited)) {
                return true; // 如果邻接节点存在环,返回true
            }
        }
        visited[cur] = 2; // 将当前节点标记为已访问
        return false; // 返回false表示不存在环
    }
}

  

3. 总结

posted on 2023-07-18 17:50  白露~  阅读(13)  评论(0编辑  收藏  举报