【LeetCode 深度优先搜索专项】不同岛屿的数量(694)

1. 题目

给定一个 m × n m \times n m×n 的二维矩阵 grid ,同时将由横向或纵向按边相接的 1 1 1 (代表陆地)所组成的集合视为岛屿,可以假定矩阵区域之外都为海水。

如果两个岛屿可以且仅可以通过平移的方式(不可进行旋转或镜像)覆盖相同的区域,就称这两个岛屿是相同的,要求返回 grid 中不同岛屿的数量。

1.1 示例

  • 示例 1 1 1

    • 输入: grid = [[1, 1, 0, 0, 0], [1, 1, 0, 0, 0], [0, 0, 0, 1, 1], [0, 0, 0, 1, 1]]
    • 输出: 1 1 1

在这里插入图片描述

  • 示例 2 2 2

    • 输入: grid = [[1, 1, 0, 1, 1], [1, 0, 0, 0, 0], [0, 0, 0, 0, 1], [1, 1, 0, 1, 1]]
    • 输出: 3 3 3

在这里插入图片描述

1.2 说明

1.3 提示

  • m == grid.length
  • n == grid[i].length
  • 1 <= m, n <= 50
  • grid[i][j] 只会是 0 0 0 或者 1 1 1

1.4 进阶

你可以使用多种方法解答这道题目么?(深度优先搜索、广度优先搜索)

2. 解法一(深度优先搜索)

2.1 分析

很显然得想办法把二维矩阵中的「岛屿」进行转化,变成比如字符串这样的类型,然后利用 set 这样的数据结构去重,最终得到不同的岛屿的个数。

如果想把岛屿转化成字符串,说白了就是序列化,序列化说白了就是遍历。

首先,对于形状相同的岛屿,如果从同一起点出发,深度优先遍历的顺序肯定是一样的。因为遍历顺序是写死在递归函数里面的,不会动态改变;所以,遍历顺序从某种意义上说就可以用来描述岛屿的形状,比如下图这两个岛屿:

在这里插入图片描述
假设它们的遍历顺序是:

下,右,上,撤销上,撤销右,撤销下

如果我用分别用 1 1 1 2 2 2 3 3 3 4 4 4 代表上下左右,用 − 1 -1 1 − 2 -2 2 − 3 -3 3 − 4 -4 4 代表上下左右的撤销(这里的撤销可以理解为递归调用的返回),那么可以这样表示它们的遍历顺序:

2 2 2 4 4 4 1 1 1 − 1 -1 1 − 4 -4 4 − 2 -2 2

最后对不同的遍历顺序进行序列化并去重之后即可得到结果。

2.2 解答

from typing import List
from json import dumps


class Solution:
    def _dfs_flood(self, grid: List[List[int]], path: List[int], i: int, j: int, direction: int):
        m, n = len(grid), len(grid[0])
        if i < 0 or i >= m or j < 0 or j >= n:
            return
        if grid[i][j] == 0:
            return
        path.append(direction)
        grid[i][j] = 0
        self._dfs_flood(grid, path, i - 1, j, 1)
        self._dfs_flood(grid, path, i + 1, j, 2)
        self._dfs_flood(grid, path, i, j - 1, 3)
        self._dfs_flood(grid, path, i, j + 1, 4)
        path.append(-direction)

    def num_distinct_islands(self, grid: List[List[int]]) -> int:
        m, n = len(grid), len(grid[0])
        islands = set()
        for i in range(m):
            for j in range(n):
                if grid[i][j] == 1:
                    path = []
                    self._dfs_flood(grid, path, i, j, 0)
                    islands.add(dumps(path))
        return len(islands)


def main():
    grid = [[1, 1, 0, 0, 0], 
            [1, 1, 0, 0, 0], 
            [0, 0, 0, 1, 1], 
            [0, 0, 0, 1, 1]]
    sln = Solution()
    print(sln.num_distinct_islands(grid))  # 2


if __name__ == '__main__':
    main()

2.3 复杂度

  • 时间复杂度: O ( m n ) O(mn) O(mn),其中 m m m n n n 分别为行数和列数。
  • 空间复杂度: O ( m n ) O(mn) O(mn)

猜你喜欢

转载自blog.csdn.net/weixin_37780776/article/details/120998782