LeetCode 210. Course Schedule II

本文介绍了使用堆栈实现的标准拓扑排序算法,包括两种解决方案:一种是深度优先搜索(DFS),另一种是广度优先搜索(BFS)。通过具体实例解释了如何在给定课程依赖关系的情况下找到正确的课程顺序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

This is standard topological sort

1: First solution, using stack.

#include <vector>
#include <stack>
#include <iostream>
#include <algorithm>
#include <unordered_map>
using namespace std;

/*
  For example 2, [[1, 0]]
  There are a total of 2 courses to take. To take course 1, you should have finished course 0
  So the correct course order is [0, 1]
  Another example:
  4, [[1, 0], [2, 0], [3, 1], [3, 2]]
  There are a total of 4 courses to take. To take course 3 you should have finished both courses
  1 and 2. Both courses 1 and 2 should be taken after you finished course 0. So one correct
  course order is [0, 1, 2, 3]
  Another correct ordering is [0, 2, 1, 3].

  Note:
  The input prerequisites is a graph represented by a list of edges, not adjacency matrices.
*/
// This is clearly to do toplogical sort.
void toplogicalSort(unordered_map<int, vector<int> > courses, unordered_map<int, bool>& visited, stack<int>& nodes, int i) {
  visited[i] = true;
  
  vector<int> edges = courses[i];
  for(int k = 0; k < edges.size(); ++k) {
    if(!visited[edges[k]]) {
      toplogicalSort(courses, visited, nodes, edges[k]);
    }
  } nodes.push(i);  // notice this line. After traversing all the nodes, push it backward.
}
vector<int> findOrder(int numCourses, vector<pair<int, int> >& prerequisites) {
  unordered_map<int, bool> visited;
  for(int i = 0; i < numCourses; ++i) {
    visited[i] = false;
  }
  unordered_map<int, vector<int> > courses;
  for(int i = 0; i < prerequisites.size(); ++i) {
    int first = prerequisites[i].first;
    int second = prerequisites[i].second;
    courses[first].push_back(second);
  }
  stack<int> nodes;
  for(int i = 0; i < numCourses; ++i) {
    if(!visited[i]) {
      toplogicalSort(courses, visited, nodes, i);
    }
  }
  vector<int> res;
  while(!nodes.empty()) {
    int tmp = nodes.top();
    nodes.pop();
    res.push_back(tmp);
  }
  return res;
}


int main(void) {
  vector< pair<int, int> > prerequisites{{1, 0}, {2, 0}, {3, 1}, {3, 2}};
  vector<int> res = findOrder(4, prerequisites);
  reverse(res.begin(), res.end());
  for(int i = 0; i < res.size(); ++i) {
    cout << res[i] << " ";
  }
  cout << endl;
}

2: Second solution. 

First find the degree 0 vertex and apply dfs search.

class Solution {
public:
    vector<int> findOrder(int numCourses, vector<pair<int, int>>& prerequisites) {
        if (numCourses == 0) return vector<int>(0, 0);
        unordered_map<int, vector<int> > adjacentList;
        vector<int> startList(numCourses, 0);
        for (auto pre : prerequisites) {
            adjacentList[pre.first].push_back(pre.second);
            startList[pre.second]++;  // this is the graph node's degree.
        }

        int visitedNodes = 0;
        vector<int> marks(numCourses, 0); // 0 indicates not marked, 1 temporary marked, 2 permanent marked
        vector<int> orders;
        while (visitedNodes < numCourses) {
            //find one unvisited node with indegree == 0
            int startNode = findOneUnvisitedNode(numCourses, startList, marks);
            // if cannot find a startNode, return false;
            if (startNode >= numCourses) return vector<int>(0, 0);
            // dfs from start node
            if (!dfs(startNode, adjacentList, marks, visitedNodes, orders)) return vector<int>(0, 0);
        }
        return orders;
    }

    int findOneUnvisitedNode(int numCourses, vector<int>& startList, vector<int>& marks) {
        int startNode = 0;
        for (; startNode < numCourses; startNode++) {
            if (startList[startNode] == 0 && marks[startNode] == 0)
                break;
        }
        return startNode;
    }

    bool dfs (int startNode, unordered_map<int, vector<int> >& adjacentList, vector<int>& marks, int & visitedNodes, vector<int>& orders) {
        if (marks[startNode] == 1) return false;
        if (marks[startNode] == 0) {
            marks[startNode] = 1;
            //visit all adjacent node
            for (auto neighbor : adjacentList[startNode]) {
                if (!dfs(neighbor, adjacentList, marks, visitedNodes, orders)) return false;
            }
            marks[startNode] = 2;
            orders.push_back(startNode);
            visitedNodes++;
        }
        return true;
    }
};


https://leetcode.com/discuss/90109/dfs-c-solution-topological-sort

https://courses.cs.washington.edu/courses/cse326/03wi/lectures/RaoLect20.pdf

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值