LeetCode-207-课程表

在这里插入图片描述

1、深度优先搜索

我们实际上可以将问题理解为,在一个有向图中发现是否有环。为了实现以上模型,我们可以利用二维数组edges记录课程与课程之间的关系;利用visited记录当前节点是否被访问过其中0表示没有被访问过,1表示已经被访问过,2表示已经遍历过该节点的所有路径均无环;利用valid记录我们当前是否需要跳出循环。

我们首先初始化edges和visited,而后选择一个没有被访问过的节点进行深度遍历,遍历过的节点将visited标记为1,而后我们遍历它指向的每一个节点:1、若该节点没有被访问过,说明之间不冲突,我们继续对新节点进行深度遍历;2、若该节点之前被访问过,说明我们现在遍历的路径是一个环,因此我们将valid = false标记此时图中有环,而后跳出循环返回结果。

class Solution {
private:
    vector<vector<int>> edges;
    vector<int> visited;
    bool valid = true;

public:
    void dfs(int u) {
        visited[u] = 1;
        for (int v: edges[u]) {
            if (visited[v] == 0) {
                dfs(v);
                if (!valid) {
                    return;
                }
            }
            else if (visited[v] == 1) {
                valid = false;
                return;
            }
        }
        visited[u] = 2;
    }

    bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
        edges.resize(numCourses);
        visited.resize(numCourses);
        for (const auto& info: prerequisites) {
            edges[info[1]].push_back(info[0]);
        }
        for (int i = 0; i < numCourses && valid; ++i) {
            if (!visited[i]) {
                dfs(i);
            }
        }
        return valid;
    }
};

2、广度优先搜索

在所有课程中,如果有课程的前置课程为空说明它可以直接上课不存在约束。因此我们可以使用队列将所有前置课程为空(即入度为0)的课程入队,而后依次出队,并将以出队元素为前置条件的课程入队,表示他们也可以直接进行上课,如此循环直至队列为空,若此时所有课程都被遍历则说明不存在环。

class Solution {
private:
    vector<vector<int>> edges;
    vector<int> indeg;

public:
    bool canFinish(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]];
        }

        queue<int> q;
        for (int i = 0; i < numCourses; ++i) {
            if (indeg[i] == 0) {
                q.push(i);
            }
        }

        int visited = 0;
        while (!q.empty()) {
            ++visited;
            int u = q.front();
            q.pop();
            for (int v: edges[u]) {
                --indeg[v];
                if (indeg[v] == 0) {
                    q.push(v);
                }
            }
        }

        return visited == numCourses;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值