平行课程leetcode1136(拓扑排序)

已知有 N 门课程,它们以 1 到 N 进行编号。

给你一份课程关系表 relations[i] = [X, Y],用以表示课程 X 和课程 Y 之间的先修关系:课程 X 必须在课程 Y 之前修完。

假设在一个学期里,你可以学习任何数量的课程,但前提是你已经学习了将要学习的这些课程的所有先修课程。

请你返回学完全部课程所需的最少学期数。

如果没有办法做到学完全部这些课程的话,就返回 -1。

示例 1:
在这里插入图片描述

输入:N = 3, relations = [[1,3],[2,3]]
输出:2
解释:
在第一个学期学习课程 1 和 2,在第二个学期学习课程 3。
示例 2:
在这里插入图片描述

输入:N = 3, relations = [[1,2],[2,3],[3,1]]
输出:-1
解释:
没有课程可以学习,因为它们相互依赖。

提示:

1 <= N <= 5000
1 <= relations.length <= 5000
relations[i][0] != relations[i][1]
输入中没有重复的关系

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/parallel-courses
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。


public class 平行课程leetcode1136拓扑排序 {
    public static int minimumSemesters(int N, int[][] relations) {
        if (N < 1 || N > 5000 || relations == null ||
                relations.length < 1 || relations.length > 5000) {
            return -1;
        }
        int[] indegree = new int[N + 1];
        Map<Integer, Set<Integer>> adj = new HashMap<>();
        for (int i = 0; i < relations.length; i++) {
            indegree[relations[i][1]]++;   // 统计节点的入度
            if (adj.containsKey(relations[i][0])) {
                Set<Integer> sets = adj.get(relations[i][0]);
                sets.add(relations[i][1]);
                adj.put(relations[i][0], sets);
            } else {
                Set<Integer> tempSets = new HashSet<>();
                tempSets.add(relations[i][1]);
                adj.put(relations[i][0], tempSets);
            }
        }

        // 寻找入度为0的节点,
        Queue<Integer> queue = new LinkedList<>();
        for (int i = 1; i < N + 1; i++) {
            if (indegree[i] == 0) {
                queue.add(i);
            }
        }


        int semester = 0;
        int finish_count = 0;

        while (queue.size() > 0) {
            semester += 1;
            Queue<Integer> newQueue = new LinkedList<>();
            for (Integer node : queue) {
                finish_count++;

                Set<Integer> sets = adj.get(node);
                if (sets != null) {
                    for (Integer neighbor : sets) {
                        // 将与这个节点相连的所有节点的入度减一
                        indegree[neighbor]--;
                        if (indegree[neighbor] == 0) {
                            newQueue.add(neighbor);
                        }
                    }
                }
            }
            queue = newQueue;
        }
        if (finish_count == N) {
            return semester;
        } else {
            return -1;
        }
    }

    public static void main(String[] args) {
//        System.out.println(minimumSemesters(25, new int[][]
//                {{5, 10}, {11, 14}, {21, 22}, {16, 19}, {21, 25}, {6, 18}, {1, 9}, {4, 7}, {10, 23}, {5, 14}, {9, 18}, {18, 21}, {11, 22}, {1, 15}, {1, 2}, {5, 18}, {7, 20}, {2, 23}, {12, 13}, {9, 14}, {10, 16}, {11, 21}, {5, 12}, {2, 24}, {8, 17}, {15, 17}, {10, 13}, {11, 16}, {20, 22}, {7, 11}, {9, 15}, {16, 22}, {18, 20}, {19, 22}, {10, 18}, {3, 20}, {16, 25}, {10, 15}, {1, 23}, {13, 16}, {23, 25}, {1, 8}, {4, 10}, {19, 24}, {11, 20}, {3, 18}, {6, 25}, {11, 13}, {13, 15}, {22, 24}, {6, 24}, {17, 20}, {2, 25}, {15, 24}, {8, 21}, {14, 16}, {5, 16}, {19, 23}, {1, 5}, {4, 22}, {19, 20}, {12, 15}, {16, 18}, {9, 13}, {13, 22}, {14, 22}, {2, 8}, {3, 13}, {9, 23}, {14, 15}, {14, 17}, {8, 20}, {9, 17}, {3, 19}, {8, 25}, {2, 12}, {7, 24}, {19, 25}, {1, 13}, {6, 11}, {14, 21}, {7, 15}, {3, 14}, {15, 23}, {10, 17}, {4, 20}, {6, 14}, {10, 21}, {2, 13}, {3, 21}, {8, 11}, {5, 21}, {6, 23}, {17, 25}, {16, 21}, {12, 22}, {1, 16}, {6, 19}, {7, 25}, {3, 23}, {11, 25}, {3, 10}, {6, 7}, {2, 3}, {5, 25}, {1, 6}, {4, 17}, {2, 16}, {13, 17}, {17, 22}, {6, 13}, {5, 6}, {4, 11}, {4, 23}, {4, 8}, {12, 23}, {7, 21}, {5, 20}, {3, 24}, {2, 10}, {13, 14}, {11, 24}, {1, 3}, {2, 7}, {7, 23}, {6, 17}, {5, 17}, {16, 17}, {8, 15}, {8, 23}, {7, 17}, {14, 18}, {16, 23}, {23, 24}, {4, 12}, {17, 19}, {5, 9}, {10, 11}, {5, 23}, {2, 9}, {1, 19}, {2, 19}, {12, 20}, {2, 14}, {11, 12}, {1, 12}, {13, 23}, {4, 9}, {7, 13}, {15, 20}, {21, 24}, {8, 18}, {9, 11}, {8, 19}, {6, 22}, {16, 20}, {22, 25}, {20, 21}, {6, 16}, {3, 17}, {1, 22}, {9, 22}, {20, 24}, {2, 6}, {9, 16}, {2, 4}, {2, 20}, {20, 25}, {9, 10}, {3, 11}, {15, 18}, {1, 20}, {3, 6}, {8, 14}, {10, 22}, {12, 21}, {7, 8}, {8, 16}, {9, 20}, {3, 8}, {15, 21}, {17, 21}, {11, 18}, {13, 24}, {17, 24}, {6, 20}, {4, 15}, {6, 15}, {3, 22}, {13, 21}, {2, 22}, {13, 25}, {9, 12}, {4, 19}, {1, 24}, {12, 19}, {5, 8}, {1, 7}, {3, 16}, {3, 5}, {12, 24}, {3, 12}, {2, 17}, {18, 22}, {4, 25}, {8, 24}, {15, 19}, {18, 23}, {1, 4}, {1, 21}, {10, 24}, {20, 23}, {4, 14}, {16, 24}, {10, 20}, {18, 24}, {1, 14}, {12, 14}, {10, 12}, {4, 16}, {5, 19}, {4, 5}, {19, 21}, {15, 25}, {1, 18}, {2, 21}, {4, 24}, {7, 14}, {4, 6}, {15, 16}, {3, 7}, {21, 23}, {1, 17}, {12, 16}, {13, 18}, {5, 7}, {9, 19}, {2, 15}, {22, 23}, {7, 19}, {17, 23}, {8, 22}, {11, 17}, {7, 16}, {8, 9}, {6, 21}, {4, 21}, {4, 13}, {14, 24}, {3, 4}, {7, 18}, {11, 15}, {5, 11}, {12, 17}, {6, 9}, {1, 25}, {12, 18}, {6, 12}, {8, 10}, {6, 8}, {11, 23}, {7, 10}, {14, 25}, {14, 23}, {12, 25}, {5, 24}, {10, 19}, {3, 25}, {7, 9}, {8, 12}, {5, 22}, {24, 25}, {13, 19}, {3, 15}, {5, 15}, {15, 22}, {10, 14}, {3, 9}, {13, 20}, {1, 10}, {9, 21}, {10, 25}, {9, 24}, {14, 20}, {9, 25}, {8, 13}, {7, 12}, {5, 13}, {6, 10}, {2, 5}, {2, 18}, {14, 19}, {1, 11}, {7, 22}, {18, 25}, {11, 19}, {18, 19}, {4, 18}, {17, 18}, {2, 11}}));

        System.out.println(minimumSemesters(3,new int[][]{{1,2},{2,3},{3,1}}));
    }
}

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值