463. 岛屿的周长
题目来源:力扣(LeetCode)https://leetcode-cn.com/problems/island-perimeter/
题目
给定一个包含 0 和 1 的二维网格地图,其中 1 表示陆地 0 表示水域。
网格中的格子水平和垂直方向相连(对角线方向不相连)。整个网格被水完全包围,但其中恰好有一个岛屿(或者说,一个或多个表示陆地的格子相连组成的岛屿)。
岛屿中没有“湖”(“湖” 指水域在岛屿内部且不和岛屿周围的水相连)。格子是边长为 1 的正方形。网格为长方形,且宽度和高度均不超过 100 。计算这个岛屿的周长。
示例 :
输入:
[[0,1,0,0],
[1,1,1,0],
[0,1,0,0],
[1,1,0,0]]
输出: 16
解释: 它的周长是下面图片中的 16 个黄色的边:
解题思路
思路:深度优先搜索
先审题,题目中说明,给定的二维网格地图中:
- 数字
1
表示陆地; - 数字
0
表示水域。
其中网格中格子水平垂直方向是相连的,但是对角线部分是不相连的。而网格中只存在一个岛屿(有一个或多个表示陆地的格子包围而成)。还有题目提到,岛屿不存在“湖”,也就是说岛屿中,仅由表示陆地的格子包围不会存在表示海域的格子。
现在题目要求岛屿的周长。
在这里我们可以先看题目示例中给的图示:
其中上面图示二维网格的表示如下:
[[0,1,0,0],
[1,1,1,0],
[0,1,0,0],
[1,1,0,0]]
图示中,黄色的边表示需计入周长的有效边。而其他黑色的边,则包含陆地与陆地之间接壤部分,或者海域与陆地不接壤的部分,这里的边都不会被计入要求的周长上。
这里,我们哪些情况的边是需要被计入计算的?
我们先看坐标为 (0, 0)
这部分,结合图示我们可以看到这里代表的是海域部分,此时它的右边是陆地,两者接壤的边是黄色的,也就是需要计算的部分。同样的,它的下边是陆地,两者接壤边也是黄色。
再看坐标 (1, 0)
部分,这块表示陆地,它除了与上下两个海域接壤需计算边之外,它与边界之间也有个黄色的边,这同样也是需要计算的部分。
下面说一下,使用深度优先搜索思路的具体做法:
- 首先从网格的左上角开始遍历,进行搜索,先找到表示陆地的格子;
- 当遍历的格子是陆地时,我们开始往四个方向进行扩散搜索,其中:
- 若从当前格子往某个方位扩散,越过边界时,那么表示当前格子与边界接壤,此时应该将与边界接壤的边计入周长中;
- 如果扩散时,发现邻近的是海域,同样的也应该将与海域接壤的边计入周长中;
- 如果扩散时,发现的是已经搜索过的格子,这里不重复计算。
- 这里注意,防止表示陆地的格子在搜索中被重复搜索,这里经过搜索的陆地格子都需要进行标记,这里我将其设为
-1
,以作区分。 - 搜索直至所有网格都被访问,最终累计的边即是所求边长。
具体的代码实现如下。
class Solution:
def islandPerimeter(self, grid: List[List[int]]) -> int:
def dfs(i, j):
# 遇到边界,海域都应该计算接壤边
if i < 0 or i >= len(grid) or j < 0 or j >= len(grid[0]) or grid[i][j] == 0:
return 1
# 如果重复访问,则不计算
if grid[i][j] == -1:
return 0
# 陆地格子要先进行标记, 设为 -1
grid[i][j] = -1
# 计算有效边(须计入周长的边)
total = 0
# 在当前陆地格子,往四个方位进行扩散搜索
for di, dj in directions:
ni = i + di
nj = j + dj
total += dfs(ni, nj)
return total
# 四个方位
directions = [(-1, 0), (0, 1), (1, 0), (0, -1)]
ans = 0
# 在网格上遍历,先找到第一块陆地格子,然后扩散
for i in range(len(grid)):
for j in range(len(grid[0])):
if grid[i][j] == 1:
ans += dfs(i, j)
return ans
这里再额外说一下,其实我们从图示中(或者叫所学的知识中)得到一些规律。
我们知道,两个正方形(边长为 1)单独计算周长时,都为 4。和为 8。但若是将两者以各自的一边进行拼接(无缝),那么拼接后的周长则为 6,减少了两个边的长度,而这两个边就是两者拼接的边。
在这道题当中,陆地之间接壤,每一个接壤都会减少 2 个边。那么这里的周长计算公式则是:
p
e
r
i
m
e
t
e
r
=
l
a
n
d
∗
4
−
b
o
r
d
e
r
∗
2
perimeter = land * 4 - border * 2
perimeter=land∗4−border∗2
这里需要求的就是
l
a
n
d
land
land 和
b
o
r
d
e
r
border
border 这两个变量,
l
a
n
d
land
land 表示的是陆地格子的数量,而
b
o
r
d
e
r
border
border 表示岛屿中,陆地之间有多少是接壤的。
以上就是主要内容。
欢迎关注
公众号 【书所集录】
如有错误,烦请指出,欢迎指点交流。