[LeetCode] 拓扑排序

(47条消息) 拓扑排序(Topological Sorting)_神奕的专栏-CSDN博客_拓扑排序

拓扑排序的原理如上。

简单的来说就是:对于有向无环图DAG来说,图内无环才能有对应的拓扑排序。

LeetCode207 课程表

207. 课程表 - 力扣(LeetCode) (leetcode-cn.com)

拓扑排序+DFS:

class Solution {
private:
    vector<vector<int>> edges; //edges[i][j]中i为前置课程,j表示对应的一系列后继课程
    vector<int> visited; //0为未搜索,1为搜索中,2为已完成
    bool valid = true; //标记结果,遇到环则更新为false

public:
    void dfs(int course) {
        visited[course] = 1; //更新 搜索中
        //遍历该前置课程的所有后继课程
        for(int c : edges[course]) {
            //如果后继点为未搜索
            if(visited[c] == 0) {
                dfs(c);
                if(!valid)
                    return;
            }
            //如果出现环 
            else if (visited[c] == 1) {
                valid = false;
                return;
            }
        }
        visited[course] = 2; //已完成
    }

    bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
        edges.resize(numCourses);
        visited.resize(numCourses);
        //把给定的课程关系转换一下,方便遍历某个结点所有的后继点
        for(const auto& edge : prerequisites) {
            int pre = edge[0], next = edge[1];
            edges[pre].push_back(next);
        }
        //遍历所有课程,对每个点都进行dfs(未出现环时)
        for(int i = 0; i < numCourses && valid; i++) {
            if(!visited[i])
                dfs(i);
        }
        return valid;
    }
};

LeetCode210 课程表II

拓扑排序+DFS

和上一题不同之处只在于多了一个记录拓扑排序的数组,该数组在dfs的末尾添加新元素,并且在返回答案时进行反转。

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

public:
    void dfs(int course) {
        visited[course] = 1;
        for(int c:edges[course]) {
            if(visited[c] == 0) {
                dfs(c);
                if(!valid)
                    return;
            }
            else if(visited[c] == 1) {
                valid = false;
                return;
            }
        }
        visited[course] = 2;
        ans.push_back(course);
    }

    vector<int> findOrder(int numCourses, vector<vector<int>>& prerequisites) {
        edges.resize(numCourses);
        visited.resize(numCourses);
        for(const auto& edge:prerequisites) {
            int pre = edge[1], next = edge[0];
            edges[pre].push_back(next);
        }

        for(int i = 0; i < numCourses && valid; i++) {
            if(!visited[i]) {
                dfs(i);
            }
        }

        if(!valid)
            return {};
        reverse(ans.begin(), ans.end());

        return ans;
    }
};

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值