边工作边刷题: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 []
                

posted @ 2016-03-25 07:13  absolute100  阅读(155)  评论(0编辑  收藏  举报