题目描述
给定一个非空01二维数组表示的网格,一个岛屿由四连通(上、下、左、右四个方向)的 1 组成,你可以认为网格的四周被海水包围。
请你计算这个网格中共有多少个形状不同的岛屿。两个岛屿被认为是相同的,当且仅当一个岛屿可以通过平移变换(不可以旋转、翻转)和另一个岛屿重合。
样例 1:
11000
11000
00011
00011
给定上图,返回结果 1。
样例 2:
11011
10000
00001
11011
给定上图,返回结果 <font color="#c7254e" face="Menlo, Monaco, Consolas, Courier New, monospace">3</font>。
注意:
11
1
和
1
11
是不同的岛屿,因为我们不考虑旋转、翻转操作。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/number-of-distinct-islands
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题目分析:
通过尝试优先遍历,找出图中存在的岛屿。还有一个需要解决的问题是如何判断2个岛屿平移后相同,每个岛屿的所有点放入一个列表,每个点用和岛屿开始位置的曼哈顿坐标表示(x0-x_start, y0-y_start),即可以判断2个岛屿是否平移相同。
代码实现:
class Solution:
def numDistinctIslands(self, grid: List[List[int]]) -> int:
if not grid or not grid[0]:
return 0
rows, cols = len(grid), len(grid[0])
seen = [[0 for _ in range(cols)] for _ in range(rows)]
dirs = [(0, -1), (0, 1), (-1, 0), (1, 0)]
def dfs_island(grid, row, col, x_from, y_from, island=None):
nonlocal seen
if island is None:
island = []
def is_valid(grid, x, y):
rows, cols = len(grid), len(grid[0])
if x < 0 or x >= rows:
return False
if y < 0 or y >= cols:
return False
return True
seen[row][col] = 1
island.append((row - x_from, col - y_from))
for dir_ in dirs:
dir_x, dir_y = dir_
x, y = row + dir_x, col + dir_y
if is_valid(grid, x, y) and grid[x][y] == 1 and seen[x][y] == 0:
dfs_island(grid, x, y, x_from, y_from, island)
return island
islands = []
def add_island(islands, island):
for ele in islands:
if ele == island:
return
islands.append(island)
for row in range(rows):
for col in range(cols):
if seen[row][col] == 0 and grid[row][col] == 1:
add_island(islands, dfs_island(grid, row, col, row, col))
return len(islands)