Leetcode207 课程表 I+II(dfs+bfs)

在这里插入图片描述
使用dfs的思想,对每个课程进行搜索。

learn[class]中存储当前课程的状态,共有三种可能:

  • learn[class] = -1【未搜索】首次遇到class,对其进行递归搜索
  • learn[class] = 0【搜索中】前序搜索过此class但还未回溯,说明遇到环,无法完成学习
  • learn[class] = 1【已完成】此class已被成功学习,无需操作

当某课程的所有前序课程,均为“已完成”状态时,将其标记为已完成。

附上代码:

class Solution {
public:
    void dfs(vector<int>& learn, map<int,vector<int>>& req, int curr){
        if(learn[curr] != -1) return;
        learn[curr] = 0;
        for(auto cla : req[curr]){
            dfs(learn, req, cla);
            if(learn[cla] != 1) return;
        }
        learn[curr] = 1;
    }

    bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
        vector<int> learn(numCourses, -1);
        map<int,vector<int>> req;
        for(int i=0; i<numCourses; i++) req[i] = vector<int>();
        for(auto x : prerequisites) req[x[0]].push_back(x[1]);
        
        for(int i=0; i<numCourses; i++){
            if(learn[i] == 1) continue;
            dfs(learn, req, i);
        }
        for(auto x : learn) if(x != 1) return false;
        return true;
    }
};

在这里插入图片描述
这道题在之前的基础上,要求输出选课的顺序。
典型的拓扑排序问题,也可以通过堆来做。
对每个课程记录还需上多少门课才能选,同时把所有0的课程加入堆中(不需要额外选课的课程)
则堆中的课程都是可以直接选择的,不断将堆中元素加入输出,并更新其他课程的所需课程。

代码:

class Solution {
public:
   
    vector<int> findOrder(int numCourses, vector<vector<int>>& prerequisites) {
        queue<int> que;
        vector<int> out;
        vector<int> idx(numCourses, 0);
        map<int, vector<int>> m;
        for(int i=0; i<numCourses; i++) m[i] = vector<int>();
        for(auto x : prerequisites) {
            m[x[1]].push_back(x[0]);
            idx[x[0]]++;
        }
        for(int i=0; i<numCourses; i++) if(idx[i] == 0) que.push(i);

        while(!que.empty()){
            int temp = que.front(); que.pop();
            out.push_back(temp);
            for(auto x : m[temp]) {
                idx[x]--;
                if(idx[x] == 0) que.push(x);
            }
        }

        if(out.size() != numCourses) return vector<int>();
        return out;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值