leetcode——【课程表】

题目

在这里插入图片描述

思路

拓扑排序问题

给定一个包含 nn 个节点的有向图 GG,我们给出它的节点编号的一种排列,如果满足:
对于图 GG 中的任意一条有向边 (u, v)(u,v),u 在排列中都出现在 v 的前面。
此问题可转换为:求解该图的拓扑排序。

DFS

设置visited数组,0代表未访问过,1代表正在访问但是还未回溯到该点,-1代表访问结束。遍历所有点,如果未访问过,则以该点进行DFS。如果此点已经访问结束,直接返回;如果此点正在访问还未回溯,设置失败跳出;如果此点未访问过,设置状态为正在访问还未回溯,遍历其连接的节点,分别对每个点进行DFS,遍历结束后设置该点状态为访问结束状态并且将该点送入结果数组。如果没有失败跳出,最后结束后反转结果数组即为拓扑排序结果。

BFS

设置结点入度统计数组,首先统计各个结点的入度,将入度为0的结点送入队列初始化队列。然后循环判断队列是否为空,非空时取出队首元素,将队首元素添加到结果数组,并将队首元素连接的节点的入度-1,将此时入度为0的结点送入队列,循环直到队列为空。如果结果数组的长度与节点数相等,则找到排序结果,若不等于节点数,则不存在拓扑排序结果。

实现

DFS
class Solution {
public:
    bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
        edges.resize(numCourses);
        visited.resize(numCourses);
        cool = false;
        for (vector<int> index : prerequisites)
            edges[index[1]].emplace_back(index[0]);
        for (int i = 0; i < numCourses && !cool; ++i)
            if (!visited[i])
                dfs(i);
        if (cool)
            return false;
        reverse(result.begin(), result.end());
        return true;
    }

    void dfs(int node) {
        if (visited[node] == -1 || cool)
            return;
        if (visited[node] == 1) {
            cool = true;
            return;
        }
        visited[node] = 1;
        for (int index : edges[node])
            dfs(index);
        visited[node] = -1;
        result.emplace_back(node);
    }

private:
    vector<vector<int>> edges;
    vector<int> result;
    vector<int> visited;
    bool cool;
BFS
class Solution {
public:
    vector<int> findOrder(int numCourses, vector<vector<int>>& prerequisites) {
        vector<vector<int>> edges(numCourses);
        vector<int> into_nums(numCourses);
        vector<int> ret;
        queue<int> queue;
        for (vector<int> index : prerequisites) {
            edges[index[1]].emplace_back(index[0]);
            into_nums[index[0]]++;
        }
        for (int i = 0; i < numCourses; ++i)
            if (into_nums[i] == 0) 
                queue.emplace(i);
        while (!queue.empty()) {
            int temp = queue.front();
            queue.pop();
            ret.emplace_back(temp);
            for (int index : edges[temp])
                if (--into_nums[index] == 0)
                    queue.emplace(index);
        }
        if (ret.size() != numCourses)
            return {};
        else
            return ret;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值