课程表1
你这个学期必须选修 numCourse 门课程,记为 0 到 numCourse-1。在选修某些课程之前需要一些先修课程。 例如,想要学习课程 0 ,你需要先完成课程 1 ,我们用一个匹配来表示他们:[0,1]。给定课程总量以及它们的先决条件,请你判断是否可能完成所有课程的学习?
示例 1:
输入: 2, [[1,0]]
输出: true
解释: 总共有 2 门课程。学习课程 1 之前,你需要完成课程 0。所以这是可能的。
示例 2:
输入: 2, [[1,0],[0,1]]
输出: false
解释: 总共有 2 门课程。学习课程 1 之前,你需要先完成课程 0;并且学习课程 0 之前,你还应先完成课程 1。这是不可能的。
import java.util.Scanner;
import java.util.Stack;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in); //eg:输入2
int numCourse = sc.nextInt();
sc.close();
int[][] matrix = new int[][]{{1,0},{0,1}};
System.out.println(ifFinishCourse(numCourse,matrix));
}
//函数ifFinishCourse,判断是否可以完成课程
public static boolean ifFinishCourse(int numCourse,int[][] matrix){
int[] indegree = new int[numCourse];
for(int i=0;i<matrix.length;i++){
indegree[matrix[i][1]]++;
}
//创建一个栈
Stack<Integer> s = new Stack<>();
for(int i=0;i<indegree.length;i++){
if(indegree[i] == 0){
s.push(i);
}
}
int count = 0; //用于计数,判断是否有环
while(!s.isEmpty()){
int tempN = s.pop();
count++;
//更新入度数组
for(int i=0;i<matrix.length;i++) {
if(matrix[i][0] == tempN){
indegree[matrix[i][1]]--;
if(indegree[matrix[i][1]] == 0){
s.push(matrix[i][1]);
}
}
}
}
if(count<numCourse){
return false;
} else {
return true;
}
}
}
课程表2
你这个学期必须选修 numCourse 门课程,记为 0 到 taskNum-1。在选修某些课程之前需要一些先修课程。 例如,想要学习课程 0 ,你需要先完成课程 1 ,我们用一个匹配来表示他们:[0,1]。给定课程总量以及它们的先决条件,请你判断完成所有课程的学习的最少次数,假设可以并行选修taskNum课程,请计算完成所有课程所需最短时间?
示例 1:
输入: 3
1
1>2
输出: 2
解释: 总共有 3 门课程,选修1个课程。学习课程 1 之前,你需要完成课程 2。总共需要2。
示例 2:
输入:9
6
1>2
2>3
2>4
4>5
6>4
8>7
输出: 4
import java.nio.charset.StandardCharsets;
import java.util.ArrayDeque;
import java.util.Queue;
import java.util.Scanner;
/**
* 拓扑排序
*
* @author
* @DATE 2024/6/22
**/
public class TopologicalSort {
public static void main(String[] args) {
Scanner cin = new Scanner(System.in, StandardCharsets.UTF_8.name());
int taskNum = cin.nextInt();
int relationNum = cin.nextInt();
int[][] relations = new int[relationNum][];
if (relationNum > 0) {
cin.nextLine();
for (int i = 0; i < relationNum; i++) {
String[] str = cin.nextLine().split(">");
relations[i] = new int[2];
relations[i][0] = Integer.parseInt(str[0]);
relations[i][1] = Integer.parseInt(str[1]);
}
}
cin.close();
System.out.println(getMinTime(taskNum, relations));
}
private static int getMinTime(int taskNum, int[][] relations) {
/**
* 创建拓扑排序
* 创建一个入度表
* 遍历入度表,把入读为0的全部入队列
* 队列出队,判断当前任务的入度是否为0,如果为0,加入队列,遍历完成就是最少次数
*/
if (taskNum == 0) {
return 0;
}
// 记录每个节点入度
int[] num = new int[taskNum];
for (int i = 0; i < relations.length; i++) {
// 入度指的是一个点被多个边指向
num[relations[i][0]]++;
}
Queue<Integer> queue = new ArrayDeque<>();
for (int i = 0; i < taskNum; i++) {
// 首先将入度为0的点添加到队列
if (num[i] == 0) {
queue.add(i);
}
}
int time = 0;
while (!queue.isEmpty()) {
int size = queue.size();
for (int i = 0; i < size; i++) {
// 当前节点出队时,将该节点的入度-1
int temp = queue.poll();
for (int j = 0; j < relations.length; j++) {
// relations[j][1]代表依赖节点 == 当前出队节点
if (relations[j][1] == temp) {
// 当前节点入度-1
num[relations[j][0]]--;
if (num[relations[j][0]] == 0) {
// 入度为0的当前节点,加入队列
queue.add(relations[j][0]);
}
}
}
}
time++;
}
return time;
}
}