zoukankan      html  css  js  c++  java
  • 【Leetcode】课程表(拓扑排序)

    题目:

    基于宽度优先搜索的拓扑排序

    思路:

    这个问题相当查找有向图中是否存在环。逐个删除入度为0的节点,当删除的节点数量等于输入的所有节点数量时,判定不存在环。

    拓扑排序最好使用邻接链表存储邻接关系,而非使用邻接矩阵。因为邻接链表在能够非常直接查找到邻接节点,查找操作耗时O(m+n),而邻接矩阵需要进行遍历才能查找到邻接节点,查找操作耗时O(n^2)。其中n为节点数量,m为边的数量。

    本算法的时间复杂度和空间复杂度都比较大,原因在于创建了邻接矩阵存储邻接关系。导致在查找邻接关系的时候,需要进行遍历操作,时间复杂度为O(n^2)。

    执行用时 :60 ms, 在所有 cpp 提交中击败了32.55%的用户
    内存消耗 :81.6 MB, 在所有 cpp 提交中击败了5.21%的用户
    class Solution {
    public:
        bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
            if(prerequisites.size() == 0)
                return true;
            
            vector< vector<int> > mat( numCourses, vector<int>(numCourses,0) );
            vector<int> numR(numCourses, 0);
            vector<int> stack(numCourses, 0);
            vector<int> tIn;
            int top = 0, count = 0;
            
            for(int i = 0; i < prerequisites.size(); ++i) {
                tIn = prerequisites[i];
                mat[tIn[1]][tIn[0]] = 1;
                numR[tIn[0]] += 1;
            }
            
            for(int j = 0; j < numCourses; ++j) {
                if(numR[j] == 0) {
                    stack[top++] = j;
                }
            }
            
            while(top > 0) {
                int gettop = stack[--top];
                count += 1;
                
                for(int k = 0; k < numCourses; ++k) {
                    if(mat[gettop][k] == 1) {
                        numR[k] -= 1;
                        
                        if(numR[k] == 0)
                            stack[top++] = k;
                    }
                }
            }
            
            if(count == numCourses )
                return true;
            else
                return false;
        }
    };

    对上述算法进行改进。将邻接矩阵换成邻接链表。时间复杂度为O(m+n),耗时大大缩小。

    执行用时 :24 ms, 在所有 cpp 提交中击败了93.35%的用户
    内存消耗 :12.9 MB, 在所有 cpp 提交中击败了19.07%的用户
    注意,这里巧妙使用vector<vector<int>>数据类型创建了“邻接链表”。
    class Solution {
    public:
        bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
            if(prerequisites.size() == 0)
                return true;
            
            vector< vector<int> > mat(numCourses);
            vector<int> numR(numCourses, 0);
            vector<int> stack(numCourses, 0);
            vector<int> tIn;
            int top = 0, count = 0;
            
            for(int i = 0; i < prerequisites.size(); ++i) {
                tIn = prerequisites[i];
                mat[tIn[1]].push_back(tIn[0]);
                numR[tIn[0]] += 1;
            }
            
            for(int j = 0; j < numCourses; ++j) {
                if(numR[j] == 0) {
                    stack[top++] = j;
                }
            }
            
            while(top > 0) {
                int gettop = stack[--top];
                count += 1;
                
                for(int k = 0; k < mat[gettop].size(); ++k) {
                    numR[mat[gettop][k]] -= 1;
                    
                    if(numR[mat[gettop][k]] == 0)
                        stack[top++] = mat[gettop][k];
                }
            }
            
            if(count == numCourses )
                return true;
            else
                return false;
        }
    };

    基于深度优先搜索的拓扑排序

    时间复杂度:排序过程为O(n+m),其中n为节点数量,m为边数量。构建邻接链表为O(m)。

    空间复杂度:邻接链表占据空间为O(m);标识数组占据空间为O(n);递归过程的栈内存最大为O(n),此时拓扑序列为一条链。

    class Solution {
    public:
        bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
            if(prerequisites.size() == 0)
                return true;
            
            vector< vector<int> > mat(numCourses);
            vector<int> flag(numCourses, 0);
            vector<int> tIn;
            
            for(int i = 0; i < prerequisites.size(); ++i) {
                tIn = prerequisites[i];
                mat[tIn[1]].push_back(tIn[0]);
            }
            
            bool ans = true;
            for(int i = 0; i < numCourses; ++i) {
                ans = ans&&dfsF(i, flag, mat); // 每一条路线不允许存在回路,所以是“&&”逻辑
            }
            return ans;
        }
        
        bool dfsF(int i, vector<int>& flag, const vector<vector<int> >& matC){
            if(flag[i] == 1)
                return true;
            
            if(flag[i] == -1)
                return false;
            
            flag[i] = -1;
            for(int j = 0; j < matC[i].size(); ++j) {
                if(dfsF(matC[i][j], flag, matC))
                    continue;
                else 
                    return false;
            }
            
            flag[i] = 1;
            return true;
        }
    };
  • 相关阅读:
    halcon三种模板匹配方法
    线阵相机与面阵相机的区别
    完整性检测
    halcon读取一张照片,并转化为灰度图像
    halcon车牌的识别
    HALCON学习之条形码实时扫描
    开关引脚测量
    ip sensor芯片级解决方案
    ip camera芯片级解决方案
    Parallel For Bug in static constructor
  • 原文地址:https://www.cnblogs.com/gdut-gordon/p/8672952.html
Copyright © 2011-2022 走看看