Leetcode: 207. Course Schedule(week6 — medium)

题目

There are a total of n courses you have to take, labeled from 0 to n-1.

Some courses may have prerequisites, for example to take course 0 you have to first take course 1, which is expressed as a pair: [0,1]

Given the total number of courses and a list of prerequisite pairs, is it possible for you to finish all courses?

示例

分析

  1. 这一道题题意是给出了一系列课程,这一些课程的修读具有先后次序,而所要解答的问题在于能否根据这一些次序完成课程修读。实际含义也就是判断给出的二元次序是否会形成环,如果形成环则相当于产生一个死锁。不能够修读这个环中的任何一门课(都有先修课程要求)
  2. 相比于课后的题目,也就是最短的修读时间,这一道题只需要进行判断能够修读完即可,所以只需要用一次dfs判断是否有回边即可
  3. 另外也可以使用类似于找最短修读时间来解决这一道题:时间消耗会比较大
    1. 首先使用vector<set<int>>来构造一个入度数组与出度数组,用来记录每一个顶点的初入度情况
    2. 接着创建flags数组用来记录每一门课的完成情况,如若已经完成着赋值为1
    3. 创建一个循环体
      1. 创建一个vector<int>类型,遍历所有的未完成的顶点,将入度为0的点计入其中
      2. 若入度的点个数为0,则:
        1. 如果flags全为1,则返回true
        2. 否则则返回false,因为这说明图中只剩下一个环
      3. 遍历该数组,利用出度数组删除相关的入度数组中相应的元素。
      4. 同时将对应的元素的flags置为1
    4. 重复以上步骤,直到跳出循环即可

题解

class Solution {
public:
    bool canFinish(int numCourse, vector<pair<int, int>>& prerequisites) {
        vector<set<int>> in = vector<set<int>>(numCourse);
        vector<set<int>> out = vector<set<int>>(numCourse);
        int flags[numCourse];
        for(auto i: flags){
            i = 1;
        }
        for(auto i: prerequisites){
            flags[i.first] = flags[i.second] = 0;
            in[i.first].insert(i.second);
            out[i.second].insert(i.first);
        }
        vector<int> queue1;
        vector<int> queue2;
        while(1){
            for(int i = 0; i < in.size(); i++){
                if(flags[i]!= 1 && in[i].size() == 0){
                    queue1.push_back(i);
                   // cout<<i << " \n";
                    flags[i] = 1;
                }
            }
            int check = 0;
            for(auto i: flags){
                if(i != 1){
                    check = 1;
                    break;
                }
            }
            if(check == 0) return true;
            //cout << queue1.size() << "h\n";
            if(queue1.size() == 0){
                for(auto i: flags){
                    if(i != 1){
                        return false;
                    }
                }
                return true;
            }
            for(auto i: queue1){
                for(auto j: out[i]){
                    in[j].erase(i);
                }
            }
            queue1.clear();
        }
    }
};

后记

以上方法比起dfs复杂度会偏高,而使用dfs则只需要进行一次dfs即可,所以如果要快的方法建议还是用dfs

 

 

猜你喜欢

转载自blog.csdn.net/qq_36347365/article/details/83031359