1. 问题描述:
你有一个用于表示一片土地的整数矩阵land,该矩阵中每个点的值代表对应地点的海拔高度。若值为0则表示水域。由垂直、水平或对角连接的水域为池塘。池塘的大小是指相连接的水域的个数。编写一个方法来计算矩阵中所有池塘的大小,返回值需要从小到大排序。
示例:
输入:
[
[0,2,1,0],
[0,1,0,1],
[1,1,0,1],
[0,1,0,1]
]
输出: [1,2,4]
提示:
0 < len(land) <= 1000
0 < len(land[i]) <= 1000
2. 思路分析:
① 从题目中可以知道我们需要找出矩阵中的每一片联通的水域的个数(注意矩阵中值为0的地方为水域),所以这是一道典型的关于连通性的问题,对于这种连通性的问题经典的做法是dfs搜索,使用dfs搜索从起点出发能够到达的所有水域,一次dfs结束表示的是从一开始的那个起点能够到达的地方都搜索过了,所以我们可以遍历二维矩阵,找出值为0的起点,然后从这个起点出发使用dfs搜索所有能够到达的点,并且在搜索的时候使用一个全局变量来进行计数,一次dfs结束那么就将全局变量的值加入到结果集中(表明一个水域的结束),因为是二维矩阵的搜索,所以我们需要标记一下访问过的点,这样才不会导致对于已经访问过的点重新访问了,对于这道题目来说可以使用将矩阵中已经访问过的点标记为1即可,下一次就不会再访问了
② 对于搜索当前的起点能够到达的区域,我们可以使用一个二维列表来表示八个不同的方向,这样我们就可以在循环中依次尝试当前的点能够到达八个方向的哪些点,然后再递归下去
3. 代码如下:
from typing import List
class Solution:
count = 0
def dfs(self, land: List[List[int]], x: int, y: int, r: int, c: int, pos: List[List]):
land[x][y] = 1
self.count += 1
# 搜索八个平行方向
for i in range(8):
x1, y1 = x + pos[i][0], y + pos[i][1]
if 0 <= x1 < r and 0 <= y1 < c and land[x1][y1] == 0:
self.dfs(land, x1, y1, r, c, pos)
def pondSizes(self, land: List[List[int]]) -> List[int]:
pos = [[-1, 0], [1, 0], [0, -1], [0, 1], [-1, -1], [1, -1], [-1, 1], [1, 1]]
res = list()
for i in range(len(land)):
for j in range(len(land[0])):
if land[i][j] == 0:
self.dfs(land, i, j, len(land), len(land[0]), pos)
res.append(self.count)
self.count = 0
return sorted(res)