DFS算法总结之课程表

课程表:

输入: 4, [[1,0],[2,0],[3,1],[3,2]]
输出: [0,1,2,3] or [0,2,1,3]
解释: 总共有 4 门课程。要学习课程 3,你应该先完成课程 1 和课程 2。并且课程 1 和课程 2 都应该排在课程 0 之后。
     因此,一个正确的课程顺序是 [0,1,2,3] 。另一个正确的排序是 [0,2,1,3] 

思路题解:

       1、如果将每个课程看成一个节点,那么按照课程之间的关系,可以生成一个有向图,图的表示方法可以用邻接矩阵表示,即二维数组。

       2、如果要生成一张可行的课程表,意味图着不能出现“环”;那么转化成有向图是否有环。

       3、通过图的遍历,而图的遍历有BFS和DFS两种思路

 

 

​法1:dfs,递归
class Solution {
public:
    vector<vector<int>> edges;//
    vector<int> visited;//visited[k]=0,1,2分别表示节点未被访问、访问中、已经访问
    vector<int> res;//
    bool vaild=true;

    void dfs(int k){//dfs(k)判断从k节点出发,判断是否有环
        visited[k]=1;//访问中
        for(const auto&it:edges[k]){//依次遍历k课程的后续课程
            if(visited[it]==0){
                dfs(it);
                if(vaild==false)    return;
            }else if(visited[it]==1){
                vaild=false;return;
            }
        }
        res.push_back(k);
        visited[k]=2;//已访问过
    }
    vector<int> findOrder(int numCourses, vector<vector<int>>& prerequisites) {
        edges.resize(numCourses);
        visited.resize(numCourses);
        for(const auto&it:prerequisites){
            edges[it[1]].push_back(it[0]);//edges[i]存储着课程i的以课程i为基础的后续课程
        }
        for(int i=0;i<numCourses&&vaild;i++){
            if(visited[i]==0)   dfs(i);//依次判断从各节点出发是否有“环”
        }
        if(vaild==false)
            return {};
        else{
            reverse(res.begin(),res.end());//结果反转
            return res;
        }
    }
};

法2:BFS,迭代
class Solution {
public:
    vector<vector<int>> edges;
    vector<int> indeg;
    vector<int> res;
    queue<int> q;
    vector<int> findOrder(int numCourses, vector<vector<int>>& prerequisites) {
        edges.resize(numCourses);
        indeg.resize(numCourses);
        for(const auto& info:prerequisites){
            edges[info[1]].push_back(info[0]);
            indeg[info[0]]++;
        }
        for(int i=0;i<numCourses;i++){
            if(indeg[i]==0) q.push(i);     
        }
        int visited=0;
        while(!q.empty()){
            int u=q.front();q.pop();
            res.push_back(u);
            visited++;
            for(const auto& it:edges[u]){
                indeg[it]--;
                if(indeg[it]==0)    q.push(it);
            }    
        }
        if(visited!=numCourses) res={};
        return res;
    }
};
​

 

 

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值