先吐槽一下自己。。。这两天犯懒了,就忘记更博客了,之前上课也是,笔记一直拖到了最后一天才上传。。。还不是很习惯每天打开博客看一看,写点东西,但是还是决定养成分享和学习的习惯。
原题:
你这个学期必须选修 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。这是不可能的。
提示:
1.输入的先决条件是由 边缘列表 表示的图形,而不是 邻接矩阵 。详情请参见图的表示法。
2.你可以假定输入的先决条件中没有重复的边。
3.1 <= numCourses <= 10^5
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/course-schedule
思路和代码:
思路:
很简单的转化成一个在有向图里找有没有圈的问题。然后用DST或者是BST遍历整个图去判断有没有圈即可。
主要流程:
建立栈s,大小为numCourse的boolean数组searched(来记录走过的点),counter:记录已经走过的路径的长度,new和next用来存储当前的节点和下一个要找的节点(因为对边缘列表不是很熟悉,直接采用了遍历找头结点的方法,导致复杂度很高。)prenew用来在找到错误结点的时候回档。
向栈中压入-1
->找到任意一个节点->找到一条边->检查边的下一个节点是否已经遍历
.->已经遍历->利用edge和prenew回档,counter- -。
.->未遍历->将new设为该点,并入栈,设标志位为true。
.->该节点下已经没有出边->next=s.pop;counter- -;
->next==-1时(说明栈已空)结束上述过程的循环。
->若此时仍有未遍历的点,将next设为该点,并重新将-1入栈,重复加粗的过程直到所有的点都已经遍历。
最后在赞一下leetcode的测试数据,那是真的全面。。无数个被我忽略的情况都考虑进去了。
再补充一点优化思路:可以先遍历一遍边表,把入度为0的点先剔除,然后把从它出去的边也去掉,然后再找有没有可以剔除的点和边。简化完之后在开始深度或者广度优先搜索就可以了。
代码:
import java.util.Stack;
public class Solution {
public static boolean canFinish(int numCourses, int[][] prerequisites) {
Stack<Integer> s = new Stack<>();
int now = -1,next = -1,prenow = -1;
int counter = 0;
int i = 0;
int j = 0;
boolean[] searched = new boolean[numCourses];
if(prerequisites.length==0||prerequisites.length==1)return true;
now = prerequisites[0][0];
next = now;
while(true) {
s.add(-1);
//s.add(now);
//searched[now]=true;
while(next!=-1) {
for(i=0;i<prerequisites.length;i++) {
if(prerequisites[i][0] == next) {
next = prerequisites[i][1];
prenow = now;
now = next;
counter++;
if(next!=-1&&searched[next]) {
if(counter>1&&s.contains(next))return false;
next = prerequisites[i][0];
now = prenow;
counter--;
continue;
}
else break;
}
}
if(i==prerequisites.length) {
searched[next] = true;
next = s.pop();
counter--;
}
else if(next!=-1&&!searched[next]){
s.add(now);
searched[now] = true;
now = next;
}
// else if(!s.empty()){
// next = s.pop();
// counter--;
// }
}
for(j=0;j < searched.length;j++)
{
if(!searched[j]) {
now = j;
next = now;
counter = 0;
break;
}
}
if(j==searched.length) {
return true;
}
}
}