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

Shortest Distance from All Buildings

要点:

  • 这种没有weight的distance题,首先想到dfs/bfs。这题因为是最短距离,所以用bfs。注意不同于Surrounded Regions,这题不是连通渲染,而是对每个’1’值点作为起点单独的bfs,而不是并行的起始点同时进queue初始化
  • 如何记录结果?bfs过程中,level是累加到某个点上的。但是并不知道是不是所有building都能到达,所以用reach来记录每个0点到达的1点(buildings)个数,最后统计的时候不考虑不能reach所有building的
  • 一个强力优化:bfs同时记录某个buildings连通的其他building个数,结束时如果不为所有building数,可以直接返回-1

细节:

  • bfs,visited在开始的时候allocate
  • 数据结构:self.reach, self.dist, visited, count
  • return True/False直接依赖一个条件的时候直接返回条件,而不要if/else检查

错误点:

  • 注意bfs的起始点是每个building,统计reach和sumLen的点是经过的0,count是对连通的1。最后结果是对所有0点
  • TypeError: 'int' object is not iterable: deque+pair的初始化极易错:错误:deque((x,y)),正确:deque([(x,y)])
  • next从deque变成list了:最后还是用单一object计数的方法
  • list comprehension中的variable不是list中local的
  • d+=1的位置:每层之外,初始为0
  • [[-1]]的corner case:如果bfs中初始count=0,不先set初始点的visited,这样初始点之后不能访问到,可以返回-1

https://repl.it/Cc62/4

from collections import deque

class Solution(object):
    def shortestDistance(self, grid):
        """
        :type grid: List[List[int]]
        :rtype: int
        """
        def bfs(grid, m, n, x, y, total):
            visited = [[False]*n for _ in xrange(m)] # error: don't use x,y
            q = deque([(x,y)]) # error 1
            count=0
            # visited[x][y]=True
            dirs = [(1,0),(0,1),(-1,0),(0,-1)]
            d = 0
            while q:
                # print q
                ql = len(q) # error 2: use single object
                d+=1
                for _ in xrange(ql):
                    x,y = q.popleft()
                    for xd,yd in dirs:
                        x0,y0 = x+xd,y+yd
                        if 0<=x0<m and 0<=y0<n and not visited[x0][y0]:
                            visited[x0][y0]=True # error 3: dont forget
                            if grid[x0][y0]==0:
                                self.dist[x0][y0]+=d
                                self.reach[x0][y0]+=1
                                q.append((x0,y0))
                            if grid[x0][y0]==1:
                                # print x0,y0
                                count+=1
            #print count, total
            return count==total
        
        m,n=len(grid),len(grid[0])
        total = sum([val for line in grid for val in line if val==1])
        self.dist = [[0 for y in xrange(n)] for x in xrange(m)]
        self.reach = [[0 for y in xrange(n)] for x in xrange(m)]
        for x in xrange(m):
            for y in xrange(n):
                if grid[x][y]==1:
                    if not bfs(grid, m, n, x, y, total):
                        return -1
        
        shortest = sys.maxint
        for x in xrange(m):
            for y in xrange(n):
                if self.reach[x][y]==total:
                   shortest = min(self.dist[x][y], shortest)
        
        return shortest
原文地址:https://www.cnblogs.com/absolute/p/5815833.html