DFS深度优先搜索和BFS广度优先搜索 leetcode 200. Number of Islands【python解法】

版权声明:转载请说明链接~~~ https://blog.csdn.net/weixin_40546602/article/details/88546583

一、深度优先搜索和广度优先搜索

DFS(Depth-First-Search),是盲目搜索算法的一种。常常用在树的遍历及图的处理上。假设当前搜索的节点记为k,深度优先搜索表示,继续探寻k节点的所有的边。搜索过程中,遇到满足条件的k+1节点,则继续搜索探寻k+1节点的所有的边。最后回溯至节点k。这个过程一直进行到已发现从源节点开始可以到达的所有节点位置。

**深度优先遍历图算法步骤:

  1. 访问起始点k;
  2. 依次从k的未被访问的邻接点出发,对图进行深度优先遍历;直至图中和k有路径相通的顶点都被访问;
  3. 若此时图中尚有顶点未被访问,则从一个未被访问的顶点出发,重新进行深度优先遍历,直到图中所有顶点均被访问过为止。

BFS(Breadth-First-Search),BFS同样属于盲目搜索算法,常常使用队列(先进先出)的数据结构来辅助实现。在python中,可以使用堆栈(pop(0))的性质进行实现。BFS是从源节点开始,沿着树(图)的宽度遍历树(图)的节点。将未被访问的节点依次压入队列,再依次读取进行遍历,直到队列为空,所有节点均被访问,算法终止。

**广度优先遍历图算法步骤:

  1. 首先将源节点放入队列中。
  2. 从队列中取出第一个节点,检验其是否满足要求。根据条件回传结果,并将它所有尚未检验过的满足条件的子节点加入队列中。
  3. 若队列为空,表示整张图都检查过了——亦即图中没有未搜寻的目标。结束搜寻并回传结果。
  4. 若队列不为空,若重复步骤2。

DFS和BFS比较:通常情况下,DFS的速度较快,且可以不适用额外的辅助空间。

二、Leetcode DFS和BFS例题

在leetcode 200. Number of Islands 题目中,分别介绍了该题目的DFS和BFS解法,用python语言实现。

题目描述:Given a 2d grid map of '1's (land) and '0's (water), count the number of islands. An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water. 即 给定 '1(陆地)和 '0'(水)的2d网格图,计算岛屿的数量。 岛被水包围,通过水平或垂直连接相邻的土地而形成。 假设网格的所有四个边都被水包围。

示例:

Input:
11000
11000
00100
00011

Output: 3

注意点:

(1)无论DFS还是BFS,在涉及到图中上下左右搜索的问题时,一般都要建立方向数组,表示向四个方向依次遍历。

        dx = [-1,1,0,0]

        dy = [0,0,-1,1]

(2) python中的可变对象和不可变对象传值问题。list、dict为可变对象,作为参数传递时,对象位置不发生改变。string、tuple以及int为不可变对象。

1、DFS算法思路:

建立一个mark数组,记录grid中满足条件的陆地‘1’对应的位置是否已被访问。

(1)标记当前搜索位置已被搜索(标记当前位置的mark数组为1)

(2)按照方向数组的四个方向,扩展4个新位置newx,newy

  (3) 若新位置不在地图范围内,则忽略

(4)如果新位置未曾到达过(mark[newx][newy]为0)、且是陆地(grid[newx][newy]为‘1’),继续DFS该位置。

class Solution(object):
    def numIslands(self, grid):
        """
        :type grid: List[List[str]]
        :rtype: int
        """
        res = 0
        if len(grid) == 0:
            return res
        m = len(grid)
        n = len(grid[0])
        
        mark = [[0]*n for i in range(m)]
        for i in range(m):
            for j in range(n):
                if mark[i][j] == 0 and grid[i][j] == '1':
                    self.dfs(mark,grid,i,j)
                    res += 1
        return res
                    
        
    # 深度优先搜索:时间优于宽度优先搜索 
    def dfs(self,mark,grid,x,y):
        mark[x][y] = 1
        dx = [-1,1,0,0] # 方向数组
        dy = [0,0,-1,1]
        m = len(grid)
        n = len(grid[0])
        # 遍历上下左右四个方向
        for i in range(4):
            newx = dx[i] + x
            newy = dy[i] + y
            if newx < 0 or newx >= m or newy >= n or newy < 0:
                continue
            if mark[newx][newy] == 0 and grid[newx][newy] == '1':
                self.dfs(mark,grid,newx,newy)

2、BFS算法思路:

建立一个mark数组,记录grid中满足条件的陆地‘1’对应的位置是否已被访问。建立一个队列,搜索使用。

(1)设置搜索队列Q(或能够满足FIFO的其他数据结构),标记mark[x][y]为1,并将待搜索的位置(x,y)push进入队列Q。

(2)只要队列不为空,则取队头元素,按照方向数组的4个方向,拓展4个新位置newx,newy。

(3)若新位置不在地图范围内, 则忽略。

(4)如果新位置未曾到达过(mark[newx][newy]为0)、 且是陆地(grid[newx][newy]为“1”),该新位置push进入队列, 并标记mark[newx][newy] = 1。

class Solution(object):
    def numIslands(self, grid):
        """
        :type grid: List[List[str]]
        :rtype: int
        """
        res = 0
        if len(grid) == 0:
            return res
        m = len(grid)
        n = len(grid[0])
        
        mark = [[0]*n for i in range(m)]
        for i in range(m):
            for j in range(n):
                if mark[i][j] == 0 and grid[i][j] == '1':
                    self.dfs(mark,grid,i,j)
                    res += 1
        return res
                    
        
    
    # 宽度优先搜索:队列,优先进入队列
    def bfs(self,mark,grid,x,y):
        dx = [-1,1,0,0] # 方向数组
        dy = [0,0,-1,1]
        m = len(mark)
        n = len(mark[0])
        # 利用堆栈模拟队列
        Q = []
        Q.append([x,y])
        mark[x][y] = 1
        while Q:
            temp = Q.pop(0) # 取出最前面的点
            x = temp[0]
            y = temp[1]
            for i in range(4):
                newx = dx[i] + x
                newy = dy[i] + y
                if newx < 0 or newx >= m or newy >= n or newy < 0:
                    continue
                if mark[newx][newy] == 0 and grid[newx][newy] == '1':
                    Q.append([newx,newy])  # 将新位置进入队列
                    mark[newx][newy] = 1
        


        

猜你喜欢

转载自blog.csdn.net/weixin_40546602/article/details/88546583