• leetcode 207. Course Schedule


    图的算法题
    题目就是求一堆课程有先修和后修的区别,这些课程能否构成拓扑排序而不矛盾;
    应该算是我做的第一个关于图的算法题,一开始毫无思路,看了网上的sloutions,发现这道题还是比较简单的,可以用bfs和dfs都可以做。感觉还是比较典型的关于图算法例题。
    这个题解讲的还是比较明白的,虽然leetcode的题解也很明白,但是是英文,我看了也是讲的差不多。
     
    bfs:
    BFS:典型的拓扑排序。原理也很简单,在一个有向图中,每次找到一个没有前驱节点的节点(也就是入度为0的节点), * 然后把它指向其他节点的边都去掉,重复这个过程(BFS),直到所有节点已被找到,或者没有符合条件的节点(如果图中有环存在)
     
     
     1 vector<unordered_set<int>> makegraph(int numCourses, vector<pair<int, int>> prerequisites){
     2     vector<unordered_set<int>> graph(numCourses);
     3    for(auto pre:prerequisites) graph[pre.second].insert(pre.first);
     4    return graph;
     5 }
     6 vector<int> compute_degrees(vector<unordered_set<int>> graph){
     7    vector<int> degrees(graph.size(),0);
     8     for(auto n:graph)
     9        for(int neigh:n)
    10           degrees[neigh]++;
    11    return degrees;
    12 }
    13 bool canFinish(int numCourses, vector<pair<int, int>>& prerequisites) {
    14    vector<unordered_set<int>> graph=makegraph(numCourses,prerequisites);
    15    vector<int> degrees=compute_degrees(graph);
    16    for(int i=0;i<numCourses;i++){
    17      int j=0;
    18      for(j;j<numCourses;j++)
    19         if(!degrees[j]) break;
    20      if(j==numCourses) return false;
    21      degrees[j]=-1;
    22      for(int neigh:graph[j])
    23          degrees[neigh]--;
    24     }
    25    return true;
    26   }
    27 };
     
    dfs
    DFS的解法,也需要建立有向图,还是用二维数组来建立,和BFS不同的是,我们像现在需要一个一维数组visit来记录访问状态, * 大体思路是,先建立好有向图,然后从第一个门课开始,找其可构成哪门课,暂时将当前课程标记为已访问, * 然后对新得到的课程调用DFS递归,直到出现新的课程已经访问过了,则返回false,没有冲突的话返回true,然后把标记为已访问的课程改为未访问
     1 //dfs
     2 vector<unordered_set<int>> makegraph(int numCourses, vector<pair<int, int>>& prerequisites){
     3    vector<unordered_set<int>> graph(numCourses);
     4    for(auto pre:prerequisites)
     5       graph[pre.second].insert(pre.first);
     6    return graph;
     7 }
     8 bool dfscycle(vector<unordered_set<int>>& graph,int i,vector<bool>& onpath,vector<bool>& visit){
     9    if(visit[i]) return false;
    10    visit[i]=onpath[i]=true;
    11    for(int neigh:graph[i])
    12        if(onpath[neigh]||dfscycle(graph,neigh,onpath,visit))
    13           return true;
    14     return onpath[i]=false;
    15 }
    16 bool canFinish(int numCourses, vector<pair<int, int>>& prerequisites) {
    17     vector<unordered_set<int>> graph=makegraph(numCourses,prerequisites);
    18     vector<bool> visit(numCourses,false),onpath(numCourses,false);
    19     for(int i=0;i<numCourses;i++)
    20        if(!visit[i]&&dfscycle(graph,i,onpath,visit))
    21           return false;
    22     return true;
    23 }
     
    在编写dfs code的时候,我发现一个很有趣的地方,之前在写函数的时候,如果不需要改变使用参数的值时,我尽量不用& 引用,担心不小心操作失误,改变了值,但是今天coding这道题的时候,由于建了一个图graph,我写函数的时候没用&,在输入量达到1000时,submission显示tle,当时我真是非常诧异,因为我跟solution写的大致相同,但我却tle了,后来查阅后发现,在函数时引用参数,是能提高程序效率的,尤其是当引用的参数非常大时,如一个图,用&提高程序效率,所以我上文中特地标了红色来提醒一下。
     
     
    用引用肯定可以提高效率,不过要看情况,只有当引用的是占用“较大的内存空间的对象或结构体变量”时,才可能节约更多的时间。简单变量的引用不会节省空间。道理是这样的:
    当实参是较大的对象或结构体变量时,如果直接传递给相应的函数形参,需要创建临时对象或结构本变量,而且还需要复制大块内存数据,这肯家比只传递一个“引用”(实际上是一种变形指针)要耗时得多。
    如果你想测试的话,你应该构造“大点”的对象或结构体变量才行。
    因为需要创建临时变量而拖累程序,而引用直接传递了地址。
  • 相关阅读:
    android自定义控件onLayout方法
    android自定义控件onMeasure方法
    activity的四种启动模式详细分析
    android屏幕适配的全攻略2--支持手机各种屏幕密度dpi
    android屏幕适配的全攻略3-动态获取手机屏幕宽高及动态设置控件宽高
    DIV滚动条
    .NET面试题6
    .NET面试题5
    .NET面试题4
    .NET面试题2
  • 原文地址:https://www.cnblogs.com/weedboy/p/6814201.html
Copyright © 2020-2023  润新知