LeetCode 207 Course Schedule

289 阅读3分钟

LeetCode 207 Course Schedule

思路

BFS或者DFS判断图中是否有环。

BFS:每次选取图中入度为0的node,然后删除该node,并将该node至其后继node的变删除,更新后继node的入度。若无法找到入度为0的node,则出现环。

DFS:在搜索过程中,使用todo数组和done数组标记各node。todo数组表示正在检查当前node的各出边,done数组表示当前node已访问过。如果在遍历过程中,遇到在todo数组内的node,表示当前搜索路径已经经过了该node,但是路径又返回至该node,说明遇到环。如果在遍历过程中,遇到不在todo,但是在done内的node,说明此node的各出边已检查完,通过该节点的出边无法形成环,那么再此访问该node的时候,也无法形成环,所以直接停止搜索,提高效率。

代码

未经优化

class Solution {
public:
    bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
        if (prerequisites.empty()) return true;
        unordered_map<int, int> degreeGraph;
        
        for (int i = 0; i < numCourses; ++i) 
            degreeGraph[i] = 0;
        
        for (int i = 0; i < prerequisites.size(); ++i) {
            degreeGraph[prerequisites[i][0]]++;
        }
        
        for (int i = 0; i < numCourses; ++i) {
            bool findZeroDegreeNode = false;
            int zeroDegreeNode = -1;
            for (int j = 0; j < numCourses; ++j) {
                if (!degreeGraph[j]) {
                    findZeroDegreeNode = true;
                    zeroDegreeNode = j;
                    degreeGraph[j] = -1;
                    break;
                }
            }
            if (!findZeroDegreeNode) return false;
            
            for (int j = 0; j < prerequisites.size(); ++j) {
                if (prerequisites[j][1] == zeroDegreeNode)
                    degreeGraph[prerequisites[j][0]]--;
            }
        }
        
        return true;
        
    }
};

BFS

解法1

class Solution {
public:
    bool canFinish(int numCourses, vector<pair<int, int>>& prerequisites) {
        graph g = buildGraph(numCourses, prerequisites);
        vector<int> degrees = computeIndegrees(g);
        for (int i = 0; i < numCourses; i++) {
            int j = 0;
            for (; j < numCourses; j++) {
                if (!degrees[j]) {
                    break;
                }
            }
            if (j == numCourses) {
                return false;
            }
            degrees[j]--;
            for (int v : g[j]) {
                degrees[v]--;
            }
        }
        return true;
    }
private:
    typedef vector<vector<int>> graph;
    
    graph buildGraph(int numCourses, vector<pair<int, int>>& prerequisites) {
        graph g(numCourses);
        for (auto p : prerequisites) {
            g[p.second].push_back(p.first);
        }
        return g;
    }
    
    vector<int> computeIndegrees(graph& g) {
        vector<int> degrees(g.size(), 0);
        for (auto adj : g) {
            for (int v : adj) {
                degrees[v]++;
            }
        }
        return degrees;
    }
};

解法2

class Solution {
public:
    bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
        vector<vector<int>> graph(numCourses, vector<int>());
        vector<int> degree(numCourses, 0);
        
        for ( const auto &pair : prerequisites) {
            graph[pair[1]].push_back(pair[0]);
            ++degree[pair[0]];
        }
        
        queue<int> qu;
        for (int i = 0; i < numCourses; ++i) 
            if (!degree[i]) qu.push(i);
        
        while (!qu.empty()) {
            int cur = qu.front();
            qu.pop();
            --numCourses;
            for (int i = 0; i < graph[cur].size(); ++i) {
                if (--degree[graph[cur][i]] == 0) qu.push(graph[cur][i]);
            }
            
        }
        
        return numCourses == 0;
        
    }
};

DFS

class Solution {
public:
    bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
        vector<vector<int>> graph = buildGraph(numCourses, prerequisites);
        // vector<int> degree = computeDegree(numCourses, prerequisites);
        vector<bool> todo(numCourses, false), done(numCourses, false);
        
        for (int i = 0; i < numCourses; ++i) {
            if (!done[i] && !acyclic(graph, todo, done, i))
                return false;
        }
        
        return true;
    }
private:
    vector<vector<int>> buildGraph(int numCourses, vector<vector<int>>& prerequisites) {
        vector<vector<int>> graph(numCourses, vector<int>());
        
        for (const auto &pair : prerequisites) {
            graph[pair[1]].push_back(pair[0]);
        }
        
        return graph;
    }
    
    vector<int> computeDegree(int numCourses, vector<vector<int>> &prerequisites) {
        vector<int> degree(numCourses, 0);
        
        for (const auto &pair : prerequisites) {
            ++degree[pair[0]];
        }
        
        return degree;
    }
    
    bool acyclic(vector<vector<int>> &graph, vector<bool> &todo, vector<bool> &done, int i) {
        if (todo[i]) return false;
        if (done[i]) return true;
        
        todo[i] = true;
        done[i] = true;
        for (const auto &v : graph[i]) {
            if (!acyclic(graph, todo, done, v))
                return false;
        }
        
        todo[i] = false;
        return true;
    }
};