整体思路很容易想到,就是从没有先修课的课程入手,逐渐找到所有课程的一个可能的顺序....
最初我用courseInfo来记录每门课程的先修课集合,通过while循环中每一次都扫描所有的courseInfo找出这一轮可以修的课程,但是超时;因为在比较差的条件下,这样的代价是n*n的...
那么不妨用courseInfo记录每门课是哪些课程的先修课,并用一个数组preNum记录每门课的先修课数量...那么我们只需要动态的维持一个stack/queue,保证其内都是可修的课程,通过对courseInfo中记录的后修课信息的修改(preNum),寻找新的可修课程并加入stack/queue。这样的代价实际上是n的。。。
public class Solution {
public int[] findOrder(int numCourses, int[][] prerequisites) {
List<HashSet<Integer>> courseInfo = new ArrayList<HashSet<Integer>>();
int[] preNum=new int[numCourses];
for( int i=0;i<numCourses;i++ )
{
courseInfo.add( new HashSet<Integer>() );
}
for( int[] pre:prerequisites )
{
if( !courseInfo.get(pre[1]).contains(pre[0]) )
{
courseInfo.get(pre[1]).add(pre[0]);
preNum[pre[0]]++;
}
}
int[] res= new int[numCourses];
int count=0;
Stack<Integer> stack=new Stack<Integer>();
// Queue<Integer> queue = new LinkedList<Integer>();
for( int i=0;i<numCourses;i++ )
{
if( preNum[i]==0 )
{
stack.push(i);
// queue.add(i);
res[count++]=i;
}
}
while( !stack.isEmpty() )
{
int course=stack.pop();
// int course=queue.poll();
for( int co:courseInfo.get(course) )
{
preNum[co]--;
if( preNum[co]==0 )
{
stack.push(co);
// queue.offer(co);
res[count++]=co;
}
}
}
if( count==numCourses )
{
return res;
}
else
{
return new int[0];
}
}
}