207.カリキュラム(トポロジカルソート)

LeetCode:207。コーススケジュール

ここに画像の説明を挿入


トポロジカルソート(カーンアルゴリズムは実際には幅優先探索のアイデアです)

ここに画像の説明を挿入

トポロジカルソートは、実際には欲張りアルゴリズムを使用します。一言で言えば貪欲アルゴリズム:すべてのステップが最適であり、全体的な状況が最適です。
貪欲のポイントは次のとおりです。現在、エントリー度が0のノードをチームに入れます。

前の頂点がない頂点がグラフから削除されるたびに、ここで実際の削除操作を行う必要はありません。次数配列を設定し、各ラウンドで次数0のノードを出力できます。それを削除し、変更します。尖ったノードの次数(-1で十分)、順番に取得されるノードシーケンスは、トポロジカルソートのノードシーケンスです。グラフ内に削除されていないノードがある場合は、「すべてのコースを完了できない」ことを意味します。



ACコード

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