207. 课程表 ( 拓扑排序 )

LeetCode:207. 课程表

在这里插入图片描述


拓扑排序(Kahn 算法,其实就是广度优先遍历的思路)

在这里插入图片描述

拓扑排序实际上应用的是贪心算法。贪心算法简而言之:每一步最优,全局就最优。
贪的点是:当前让入度为 0 的那些结点入队;

每一次都从图中删除没有前驱的顶点,这里并不需要真正的做删除操作,我们可以设置一个入度数组,每一轮都输出入度为 0 的结点,并移除它、修改它指向的结点的入度( -1 即可),依次得到的结点序列就是拓扑排序的结点序列。如果图中还有结点没有被移除,则说明“不能完成所有课程的学习”。



AC Code

class Solution {
    
    
    public boolean canFinish(int numCourses, int[][] p) {
    
    
        // 拓扑排序 - 广度优先遍历的思路
        int[] inDegree = new int[numCourses];
        HashSet<Integer>[] adj = new HashSet[numCourses];
        
        for(int i = 0; i < numCourses; i++) adj[i] = new HashSet<>();

        int len = p.length;
        for(int i = 0; i < len; i++) {
    
    
            inDegree[p[i][0]]++;
            adj[p[i][1]].add(p[i][0]);
        }

        Queue<Integer> queue = new LinkedList<>();
        
        // 首先加入入度为 0 的结点
        for(int i = 0; i < numCourses; i++) {
    
    
            if(inDegree[i] == 0) queue.add(i);
        }
		
		// 记录已经出队的课程数量
        int cnt = 0;
        while(!queue.isEmpty()) {
    
    
            int num = queue.poll();
            cnt++;
            // 遍历当前出队结点的所有后继结点
            for(Integer idx : adj[num]) {
    
    
                inDegree[idx]--;
                if(inDegree[idx] == 0) {
    
    
                    // 入度为 0 了
                    queue.add(idx);
                }
            }
        }

        // 移除掉的课程是否与总课程数相等
        return cnt == numCourses;
    }
}




参考: 拓扑排序、深度优先遍历

猜你喜欢

转载自blog.csdn.net/qq_43765535/article/details/112783057