zoukankan      html  css  js  c++  java
  • BFS 基础写法 —— 以 LeetCode #1091 Shortest Path in Binary Matrix 为例

    Question

    In an N by N square grid, each cell is either empty (0) or blocked (1).

    clear path from top-left to bottom-right has length k if and only if it is composed of cells C_1, C_2, ..., C_k such that:

    • Adjacent cells C_i and C_{i+1} are connected 8-directionally (ie., they are different and share an edge or corner)
    • C_1 is at location (0, 0) (ie. has value grid[0][0])
    • C_k is at location (N-1, N-1) (ie. has value grid[N-1][N-1])
    • If C_i is located at (r, c), then grid[r][c] is empty (ie. grid[r][c] == 0).

    Return the length of the shortest such clear path from top-left to bottom-right.  If such a path does not exist, return -1.

    Example 1:

    Input: [[0,1],[1,0]]
    
    
    Output: 2
    
    

    Example 2:

    Input: [[0,0,0],[1,1,0],[1,1,0]]
    
    
    Output: 4
    
    

    Note:

    1. 1 <= grid.length == grid[0].length <= 100
    2. grid[r][c] is 0 or 1

    解析

    简单来说就是经典的BFS路径搜索,从左上角走到右下角,0是通路,1是障碍。

    先给出最简洁的写法:

    class Solution:
        def shortestPathBinaryMatrix(self, grid: List[List[int]]) -> int:
            n = len(grid)
            if grid[0][0] or grid[n-1][n-1]:
                return -1
            record = [(0,0,1)]
            for i, j, d in record:
                if i == n-1 and j == n-1: return d
                for x, y in ((i-1,j-1),(i-1,j),(i-1,j+1),(i,j-1),(i,j+1),(i+1,j-1),(i+1,j),(i+1,j+1)):
                    if 0 <= x < n and 0 <= y < n and not grid[x][y]:
                        record.append((x, y, d+1))
                        grid[x][y] = 1
            return -1

    用 record 这个list来记录状态,然后直接一边在后面不停加上下一层的记录,一边iterate

    注意到 由于是BFS,采用将已经过的grid置为1来避免重复访问(BFS才能这样做)

    即便如此简洁,此方法还是有一些问题,因此更好的方法为:

    class Solution:
        def shortestPathBinaryMatrix(self, grid: List[List[int]]) -> int:
            if not grid or grid[0][0] or grid[-1][-1]: 
                return -1
            
            m, n = len(grid), len(grid[0])
            front, end, level = set([(0, 0)]), set([(m-1,n-1)]), 1
            
            while front:
    
                # intersection
                if front & end: 
                    return level
                
                for x, y in front: 
                    grid[x][y] = 1
                
                front = set((x+dx, y+dy) for x, y in front for dx, dy in [(1,1),(1,-1),(-1,1),(-1,-1),(0,1),(0,-1),(-1,0),(1,0)] if 0<=x+dx<m and 0<=y+dy<n and grid[x+dx][y+dy]==0)
                
                level += 1
                
                if len(front) > len(end): 
                    front, end = end, front
            return -1
            

    此方法解决了两个问题:

    1. 更新每一层存的状态,减小内存空间

    2. level只需一个变量存就够了(因为是BFS)

    注意其采用了set而不用list,可以减少重复情况带来的重复计算

    参考:

    https://leetcode.com/problems/shortest-path-in-binary-matrix/discuss/312827/Python-Concise-BFS

  • 相关阅读:
    opencv检测运动物体的基础_特征提取
    混合高斯建模
    计算机视觉领域的一些牛人博客,超有实力的研究机构等的网站链接
    opencv视频读取问题
    混合高斯模型背景显示
    图像显著区域检测代码及其效果图 saliency region detection
    opencv宏
    目标检测与转自背景减除
    混合高斯模型不显示背景
    error C3872: “0x3000”: 此字符不允许在标识符中使用错误 的解决办法
  • 原文地址:https://www.cnblogs.com/sbj123456789/p/12275446.html
Copyright © 2011-2022 走看看