leetcode Course Schedule系列问题,拓补排序,有向无环图

能进行拓补排序的图必须是有向无环图,直接用DFS判断图里面是否存在环,即不能存在回边,用两个时钟数组记录每个节点的进入时钟pre和返回时钟post,回边有这样的特性,如果一条边(u,v)是一条回边,那么pre(u)>pre(v)post(u)

class Solution {
public:
    bool canFinish(int numCourses, vector>& prerequisites) {
        unordered_map> adjTable;
        for (int i = 0; i < prerequisites.size(); i++) {
            adjTable[prerequisites[i].first].push_back(prerequisites[i].second);
        }
        const int arraySize = numCourses;
        bool visited[arraySize];
        int preClock[arraySize];
        int postClock[arraySize];
        int globalClock = 0;
        for (int i = 0; i < arraySize; i++) {
            visited[i] = false;
            preClock[i] = -1;
            postClock[i] = -1;
        }
        stack DFSStack;
        for (int i = 0; i < numCourses; i++) {
            if (!visited[i]) {
                DFSStack.push(i);
                while (!DFSStack.empty()) {
                    int currentNode = DFSStack.top();
                    preClock[currentNode] = globalClock;
                    globalClock++;
                    visited[currentNode] = true;
                    int count = 0;
                    for (int j = 0; j < adjTable[currentNode].size(); j++) {
                        if (!visited[adjTable[currentNode][j]]) {
                            DFSStack.push(adjTable[currentNode][j]);
                            count++;
                        } else if (preClock[currentNode] > preClock[adjTable[currentNode][j]] && postClock[adjTable[currentNode][j]] == -1) {//判断回边的条件
                            return false;
                        }
                    }
                    if (count == 0) {
                        DFSStack.pop();
                        postClock[currentNode] = globalClock;
                        globalClock++;
                    }
                }
            }
        }
        return true;
    }
};

第二题仍然按照这个思路,不过这里要返回排序结果,按照一种拓补排序的算法,给每个节点记录preClock和postClock,按照postClock的递减顺序排序的话就是一种合法的拓补排序结果,而且深搜的时候,当且仅当节点被pop出栈的时候才会计算它的postClock,所以也不需要显式计算postClock,只需要每次pop节点的时候将这个节点插到结果向量的开头就可以了。

算法描述:

TOPOLOGICAL-SORT(G)
1 call DFS(G) to compute finishing times post[v] for each vertex v
2 as each vertex is finished, insert it onto the front of a linked list
3 return the linked list of vertices
算法复杂度:O(V+E)
代码:

class Solution {
public:
    vector findOrder(int numCourses, vector>& prerequisites) {
        unordered_map> adjTable;
        for (int i = 0; i < prerequisites.size(); i++) {
            adjTable[prerequisites[i].second].push_back(prerequisites[i].first);
        }
        int globalClock = 0;
        const int vecSize = numCourses;
        vector resultVec;
        stack nodeStack;
        int preClock[vecSize], postClock[vecSize];
        bool visited[vecSize];
        for (int i = 0; i < vecSize; i++) {
            preClock[i] = -1;
            postClock[i] = -1;
            visited[i] = false;
        }
        for (int startNode = 0; startNode < numCourses; startNode++) {
            if (visited[startNode]) {
                continue;
            }
            nodeStack.push(startNode);
            visited[startNode] = true;
            preClock[0] = globalClock;
            globalClock++;
            while (!nodeStack.empty()) {
                int curNode = nodeStack.top();
                bool pushFlag = false;
                for (int i = 0; i < adjTable[curNode].size(); i++) {
                    if (!visited[adjTable[curNode][i]]) {
                        nodeStack.push(adjTable[curNode][i]);
                        visited[adjTable[curNode][i]] = true;
                        preClock[adjTable[curNode][i]] = globalClock;
                        globalClock++;
                        pushFlag = true;
                        break;
                    } else if (preClock[adjTable[curNode][i]] < preClock[curNode] && postClock[adjTable[curNode][i]] == -1) {
                        return {};
                    }
                }
                if (!pushFlag) {
                    nodeStack.pop();
                    postClock[curNode] = globalClock;
                    globalClock++;
                    resultVec.insert(resultVec.begin(), curNode);
                }
            }
        }
        return resultVec;
    }
};







你可能感兴趣的:(算法刷题)