Leetcode 207. 课程表

文章介绍了两种方法来解决LeetCode207问题,即判断课程表中是否存在环。第一种方法使用深度优先搜索(DFS)配合回溯检测环;第二种方法采用拓扑排序,通过维护入度队列来确定是否存在环。两种方法均确保在无环的情况下完成所有课程。
摘要由CSDN通过智能技术生成

题目

在这里插入图片描述
Leetcode 207. 课程表

代码(首刷看解析)

class Solution {
public:
    bool hasCycle;  // 有没有环
    vector<bool> onPath;    // 记录一次traverse递归经过的结点(回溯)
    vector<bool> visited;   // 记录遍历过的结点,避免重复计算
    bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
        auto map = build(numCourses, prerequisites);
        visited.resize(numCourses, false);
        onPath.resize(numCourses, false);
        for(int i = 0; i < numCourses; i++) {
            traverse(map, i);   // 保证从每一个结点开始都没有环
        }
        return !hasCycle;
    }
    void traverse(vector<vector<int>>& graph, int s) {// s代表指向的结点
        if(onPath[s]) 
            hasCycle = true;
        if(visited[s] || hasCycle)
            return;
        visited[s] = true;  // 该结点已经访问过
        onPath[s] = true;
        for(int t : graph[s]) {
            traverse(graph, t);
        }
        onPath[s] = false;  // 回溯
    }

    vector<vector<int>> build(int numCourses, vector<vector<int>>& prerequisites) {
        vector<vector<int>> map(numCourses);
        for(auto& edge : prerequisites) {
            map[edge[1]].push_back(edge[0]);
        }
        return map;
    }
};

代码(10.1 二刷看解析)

class Solution {
public:
    vector<vector<int>> edges;
    vector<int> indeg;
    bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
        edges.resize(numCourses);
        indeg.resize(numCourses);
        for(auto& info : prerequisites) {
            edges[info[1]].push_back(info[0]);
            indeg[info[0]]++;   // 入度
        }
        queue<int> q;
        for(int i = 0; i < numCourses; i++) {
            if(indeg[i] == 0) {
                q.push(i);
            }
        }
        int visited = 0;
        while(!q.empty()) {
            visited++;  // 说明有一个节点入度为0了,+1,只有最后所有节点的入度都为0了,才能说明没有环
            int u = q.front();
            q.pop();
            for(int v : edges[u]) {
                indeg[v]--;
                if(indeg[v] == 0) 
                    q.push(v);
            }
        }
        return visited == numCourses;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值