207. Course Schedule(課程安排)

207. Course Schedule(課程安排)

1 問題描述

There are a total of n courses you have to take, labeled from 0 to n-1.Some courses may have prerequisites, for example to take course 0 you have to first take course 1, which is expressed as a pair: [0,1]Given the total number of courses and a list of prerequisite pairs, is it possible for you to finish all courses?

已知有n個課程,標記從0至n-1,課程之間是有依賴關係的,例如希望完成0課程,可能需要先完成1課程。已知n個課程的依賴關係,求是否可以將n個課程全部完成。

Example 1:

Input: 2, [[1,0]] 
Output: true
Explanation: There are a total of 2 courses to take. 
             To take course 1 you should have finished course 0. So it is possible.

Example 2:

Input: 2, [[1,0],[0,1]]
Output: false
Explanation: There are a total of 2 courses to take. 
             To take course 1 you should have finished course 0, and to take course 0 you should
             also have finished course 1. So it is impossible.

Note:

  1. The input prerequisites is a graph represented by a list of edges, not adjacency matrices. Read more about how a graph is represented.
  2. You may assume that there are no duplicate edges in the input prerequisites.

2 思路

  • 使用深度優先遍歷:對輸入進行分析,原始問題可以轉換爲有向圖問題,當有向圖無環時返回True,當有向圖有環時返回False
  • 使用寬度優先遍歷:只將入度爲0的點添加至隊列。當完成一個頂點的搜索(從隊 列取出),它指向的所有頂點入度都減1,若此時某頂點入度爲0則添加至隊列,若完 成寬度搜索後,所有的點入度都爲0,則圖無環,否則有環。

3 C++實現

  • 圖的實現
struct GraphNode{
	int label;
	std::vector<GraphNode *> neighbors;
	GraphNode(int x) : label(x) {};
};
  • 方法一:深度優先遍歷
class Solution {
public:
    bool canFinish(int numCourses, vector<pair<int, int>>& prerequisites) {
        vector<GraphNode *> graph;
        vector<int> visit;
        //創建圖
        for(int i=0; i<numCourses; i++) {
            graph.push_back(new GraphNode(i));
            visit.push_back(-1);
        }

        //連接圖
        for(int i=0; i<prerequisites.size(); i++) {
            GraphNode* begin = graph[prerequisites[i].second];
            GraphNode* end = graph[prerequisites[i].first];
            begin->neighbors.push_back(end);
        }

        //遍歷
        for(int i=0; i<graph.size(); i++) {
            if(visit[i] == -1 && !DFS_graph(graph[i], visit))
                return false;
        }
        //回收內存
        for(int i=0; i<graph.size(); i++) {
            delete graph[i];
        }

        return true;
    }

private:
    bool DFS_graph(GraphNode *node, vector<int> &visit) {
        //節點訪問控制,-1表示沒有訪問,0表示正在訪問,1表示訪問完成
        visit[node->label] = 0;
        for(int i=0; i<node->neighbors.size(); i++) {
            if(visit[node->neighbors[i]->label] == -1) {
                if(DFS_graph(node->neighbors[i], visit) == 0)
                    return false;
            }
            else if(visit[node->neighbors[i]->label] == 0)
                return false;
        }
        visit[node->label] = 1;
        return true;
    }
};
  • 方法二,寬度優先(拓撲結構)
class Solution {
public:
    bool canFinish(int numCourses, vector<pair<int, int>>& prerequisites) {
        vector<GraphNode *> graph;
        vector<int> degree;
        //創建圖
        for(int i=0; i<numCourses; i++) {
            graph.push_back(new GraphNode(i));
            degree.push_back(0);
        }

        //連接圖
        for(int i=0; i<prerequisites.size(); i++) {
            GraphNode* begin = graph[prerequisites[i].second];
            GraphNode* end = graph[prerequisites[i].first];
            begin->neighbors.push_back(end);
            degree[prerequisites[i].first]++;
        }

        queue<GraphNode *> Q;
        for(int i=0; i<degree.size(); i++) {
            if(degree[i] == 0)
                Q.push(graph[i]);
        }

        while(!Q.empty()) {
            GraphNode* node = Q.front();
            Q.pop();
            for(int i=0; i<node->neighbors.size(); i++) {
                degree[node->neighbors[i]->label]--;
                if(degree[node->neighbors[i]->label] == 0)
                    Q.push(node->neighbors[i]);
            }
        }

        //回收內存
        for(int i=0; i<graph.size(); i++) {
            delete graph[i];
        }

        //回收內存
        for(int i=0; i<degree.size(); i++) {
            if (degree[i]){
                return false;
            }
        }
        return true;
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章