207. 课程表
总结
- DFS 走迷宫式,所以要用状态来标记是否走过这个点:0 未搜索 1 搜索中 2 已完成
- BFS(拓扑排序) 将入度为0的点依次入queue
- 取出一个之后,将这个点去掉,指向的下面节点入度-1,依次加入queue
- 取出……
- 两者方法,前面都要对prerequisites预处理,得到每个节点对应的list(记录前驱结点s 或 后继节点s)
- dfs: 记载前驱节点还是后继都可以,本质是判断里面有没有环,正着走反着走都可以
- bfs:记载后继节点,入度为0的点去掉后,后继节点入度减1
DFS
递归
public boolean canFinish2(int numCourses, int[][] prerequisites) {
List<Integer>[] preCourse = new List[numCourses];
int[] state = new int[numCourses];
for (int i = 0; i < prerequisites.length; i++) {
int cur = prerequisites[i][0];
int pre = prerequisites[i][1];
if (preCourse[pre] == null){
List li = new ArrayList<Integer>();
li.add(cur);
preCourse[pre] = li;
}else{
preCourse[pre].add(cur);
}
}
for (int i = 0; i < numCourses; i++) {
if(!dfs(i,preCourse,state)) return false;
}
return true;
}
public static boolean dfs(int i,List<Integer>[] preCourse,int[] state){
if (preCourse[i]==null || state[i]==2) return true;
if (state[i]==1) return false;
state[i] = 1;
for (int j = 0; j < preCourse[i].size(); j++) {
if(!dfs(preCourse[i].get(j),preCourse,state)) return false;
}
state[i] = 2;
return true;
}
非递归(Stack)
public boolean canFinish1(int numCourses, int[][] prerequisites) {
List<Integer>[] preCourse = new List[numCourses];
int[] state = new int[numCourses];
for (int i = 0; i < prerequisites.length; i++) {
int cur = prerequisites[i][0];
int pre = prerequisites[i][1];
if (preCourse[pre] == null){
List li = new ArrayList<Integer>();
li.add(cur);
preCourse[pre] = li;
}else{
preCourse[pre].add(cur);
}
}
Stack<Integer> stack = new Stack<>();
for (int i = 0; i < numCourses; i++) {
if (preCourse[i]==null || state[i]==2) continue;
state[i] = 1;
stack.add(i);
loop:while (!stack.isEmpty()){
int pt = stack.peek();
if (preCourse[pt]==null ){
state[pt] = 2;
stack.pop();
}else{
for (Object obj :preCourse[pt]) {
int li = (int) obj;
if (state[li]==2){
continue;
}
if (state[li]==0){
state[li] = 1;
stack.add(li);
continue loop;
}else if (state[li]==1){
return false;
}
}
state[pt] = 2;
stack.pop();
}
}
}
return true;
}
BFS
递归(depth)
public boolean canFinish4(int numCourses, int[][] prerequisites) {
List<Integer>[] postCourse = new List[numCourses];
int[] inNum = new int[numCourses];
for (int i = 0; i < prerequisites.length; i++) {
int cur = prerequisites[i][0];
int pre = prerequisites[i][1];
if (postCourse[pre] == null){
List li = new ArrayList<Integer>();
li.add(cur);
postCourse[pre] = li;
}else{
postCourse[pre].add(cur);
}
inNum[cur]++;
}
int num=0;
int[] depth = new int[numCourses];
Arrays.fill(depth,Integer.MAX_VALUE);
for (int i = 0; i < numCourses; i++) {
if (inNum[i]==0){
depth[i] = 0;
}
}
for (int i = 0; i < numCourses; i++) {
if (inNum[i]==0) num+=bfs(i,postCourse,inNum,depth,0);
}
return num==numCourses;
}
public int bfs(int cur,List<Integer>[] postCourse,int[] inNum,int[] depth,int level){
if (depth[cur]!=level) return 0;
int num=1;
for (int i = 0; postCourse[cur]!=null&&i < postCourse[cur].size(); i++) {
int nextI = postCourse[cur].get(i);
depth[nextI] = level+1;
inNum[nextI]--;
}
for (int i = 0; postCourse[cur]!=null&&i < postCourse[cur].size(); i++) {
int nextI = postCourse[cur].get(i);
if ( inNum[nextI] == 0){
num+=bfs(postCourse[cur].get(i),postCourse,inNum,depth,level+1);
}
}
return num;
}
非递归(Queue)
public boolean canFinish3(int numCourses, int[][] prerequisites) {
List<Integer>[] preCourse = new List[numCourses];
int[] inNum = new int[numCourses];
for (int i = 0; i < prerequisites.length; i++) {
int cur = prerequisites[i][0];
int pre = prerequisites[i][1];
if (preCourse[pre] == null){
List li = new ArrayList<Integer>();
li.add(cur);
preCourse[pre] = li;
}else{
preCourse[pre].add(cur);
}
inNum[cur]++;
}
Queue<Integer> queue = new LinkedList<>();
for (int i = 0; i < numCourses; i++) {
if (inNum[i]==0) queue.offer(i);
}
int visited = 0;
while (!queue.isEmpty()){
Integer cur = queue.poll();
visited++;
for (int i = 0; preCourse[cur]!=null&&i < preCourse[cur].size(); i++) {
inNum[preCourse[cur].get(i)]--;
if (inNum[preCourse[cur].get(i)] == 0){
queue.offer(preCourse[cur].get(i));
}
}
}
return visited==numCourses;
}