边工作边刷题:70天一遍leetcode: day 48

Reconstruct Itinerary

要点:注意这题不是让找cycle,只需要从”JFK"开始cover所有站就可以。所以基本方法就是按图做dfs遍历直到找到一条valid的路径

  • dfs找路径的要点有二:1是返回boolean来表示是否找到,从而可以直接返回,2是在每一个点分支要不断push=>pop来backtrack
  • 因为同一站可能在同一路径上经过多次,所以每层处理完了一个destination就要从当前分支中remove,下层返回后又要加入分支backtrack。这里就需要loop的同时remove/add,所以不能用for each loop,而是要按初始结点个数。
  • 这里的一个难点是因为要保持分支遍历的顺序,所以要用queue(FIFO)来remove/add分支:python中是deque(注意list模拟queue的效率不好)
  • 结束条件是res.size()==n。这里假设了ticket都会用光的。

错误点:

  • 因为用的是defaultdict,所以要检查下一个结点是否在graph里。注意,某一站可能不在任何ticket的出发点
  • 因为图邻接点有限,所以用TreeSet远慢于直接用list

class Solution(object):
    def findItinerary(self, tickets):
        """
        :type tickets: List[List[str]]
        :rtype: List[str]
        """
        def dfs(graph, res, n):
            if len(res)==n:
                return True
            source = res[-1]
            # print graph, source
            if source in graph: # error 1: if no check, problem with defaultdict
                for i in xrange(len(graph[source])): # error 3: similar to bfs, loop while remove/get back
                    # to = graph[source][i] error 3/4: can't loop on index:  
                    to = graph[source].popleft() # error 2: remove it so that not used anymore on the same path
                    res.append(to)
                    if dfs(graph, res, n):
                        return True
                    res.pop()
                    graph[source].append(to)
            return False
        
        graph = collections.defaultdict(list)
        for t in tickets:
            graph[t[0]].append(t[1])
        
        for k in graph:
            graph[k].sort()
            graph[k]=collections.deque(graph[k]) # error 2: should use a deque
        
        # print graph
        res = []
        res.append("JFK")
        dfs(graph, res, len(tickets)+1)
        return res
        
        

posted @ 2016-06-26 04:12  absolute100  阅读(132)  评论(0编辑  收藏  举报