zoukankan      html  css  js  c++  java
  • 边工作边刷题:70天一遍leetcode: day 99

    MHT

    [先说有向图,再说无向图]
    leetcode有三道题用到topological sort: course schedule I/II, minimum height tree(MHT)。course schedule是directed graph而MHT是undirected graph。

    Course Schedule

    • input: 边的List,因为要bfs/dfs的过程要沿着每一个结点的neighbors populate,所以要转化为adjacent matrix或者adjacent list的表示
    • output: I是判断是否可以topological sort(即graph没有环),II要求输出排序的课程
    • dfs的方法
      • idea:每一条dfs的路径都是一段partial order,两个目标:构建多有partial order的路径,判断是否有环
      • curRec:当前的partial order路径,res:结果队列,根据topological order,最底层排在头,所以当前node在dfs recursion之后近结果队列
      • 环的判断:对于directed graph,不能用visited来判断环,比如下图的例子。visited数组的作用是排除多余的dfs搜索。环只能发生在同一dfs搜索路径下,所以通过curRec set来track。同时function的return会populate back到顶层
      • 搜索的起点可能是一条完整连通路径的任何一点,从这点开始,可以覆盖到底,因此路径上的其他node都是在topological sequence靠后的位置,所以在结果里也是后入q的。同时由于visited数组,可以排除重复进res的情况
    • bfs的方法
      • 基本:用q来maintain层级,最终q中元素的顺序就是排序顺序
      • indegree数组来保存每个结点当前的入度,初始可以通过遍历adjacent list得到
      • 从所有入度为0的结点开始,如果其neighbor的入度-1==0,说明是下一层的结点,入q。这样一层层遍历直到没有下一层产生。
      • loop invariant:只需要排序不需要结果返回最后一层的结点,可以用!q.isEmpty(),而每个iteration只出队列一个结点。如果已知当前为无环图,也可以存一个待处理node的set: nodes,当neighbor进q后从nodes里去掉

    MHT
    对于undirected graph,更新indegree要同时更新边的两个结点,indegree为1即为leaf。注意如果是孤立结点,入度可以为0,所以初始化的检测条件是indegree<=1
    因为要返回树的根(可能是一个也可能是两个),即bfs的最后一层,需要用逐层的方式做bfs,这里用到两个q:q:全是indegree<=1的, bfs当前层,qnext: bfs的下一层

    class Solution(object):
        def findMinHeightTrees(self, n, edges):
            """
            :type n: int
            :type edges: List[List[int]]
            :rtype: List[int]
            """
            adjList = [set() for i in range(n)]
            for e in edges:
                adjList[e[0]].add(e[1])
                adjList[e[1]].add(e[0])
                
            q = []
            for i in range(len(adjList)):
                if len(adjList[i])==1 or len(adjList[i])==0:
                    q.append(i)
    
            while q:
                qnext = []
                for i in range(len(q)):
                    for e in adjList[q[i]]:
                        adjList[e].remove(q[i])
                        if len(adjList[e])==1:
                            qnext.append(e)
                            
                if not qnext: return q
                q=qnext
            return []
                    
    
    
  • 相关阅读:
    Git
    Spring
    Linux
    Linux
    Linux
    Linux
    Linux
    Linux
    Linux
    Linux
  • 原文地址:https://www.cnblogs.com/absolute/p/5983283.html
Copyright © 2011-2022 走看看