导语
leetcode刷题笔记记录,主要记录题目包括:
Leetcode 200. 岛屿数量
题目描述
给你一个由 '1'(陆地)和 '0'(水)组成的的二维网格,请你计算网格中岛屿的数量。
岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。
此外,你可以假设该网格的四条边均被水包围。
示例 1:
输入: grid = [ ["1","1","1","1","0"],
["1","1","0","1","0"],
["1","1","0","0","0"],
["0","0","0","0","0"]
]
输出: 1
示例 2:
输入: grid = [ ["1","1","0","0","0"],
["1","1","0","0","0"],
["0","0","1","0","0"],
["0","0","0","1","1"]
]
输出: 3
提示:
m == grid.lengthn == grid[i].length1 <= m, n <= 300grid[i][j]的值为'0'或'1'
解法
上一篇博客使用dfs解决这个问题,这里我们使用bfs来解决这个问题: 当然了,这里是使用广度优先搜索(BFS)解决“岛屿数量”问题的整体思路:
-
初始化岛屿数量为零:我们从一个没有发现任何岛屿的状态开始。
-
创建一个队列:这个队列将用于BFS过程中,储存我们要检查的网格坐标。
-
遍历网格:我们将遍历整个二维网格,寻找陆地(即标记为
'1'的格子)。 -
发现新岛屿时:每当我们遇到一个还未标记(不是
'2')的陆地(即'1'):- 岛屿数量加一。
- 将该陆地坐标添加到队列中。
- 标记该陆地为已访问(在这个例子里,我们用
'2'标记)。
-
广度优先搜索(BFS):然后我们执行以下步骤,直到队列为空:
- 取出队列中的一个坐标(这是一个已经被标记为已访问的陆地)。
- 查找这个坐标的所有邻居(即上、下、左、右四个方向)。
- 对于每一个未被访问过的邻居(即标记为
'1'):- 标记它为已访问(标记为
'2')。 - 将它加入队列。
- 标记它为已访问(标记为
-
完成搜索:当队列为空,即意味着我们已经访问了与初始发现的陆地坐标相连的所有陆地,也就是说,我们已经完整地找到了一个岛屿。
-
返回结果:遍历完整个二维网格后,返回岛屿数量。
这个算法使用BFS,确保了每一个岛屿只会被计算和访问一次。时间复杂度是 (O(m \times n)),其中 (m) 和 (n) 分别是网格的行数和列数。
from typing import List
from collections import deque
class Solution:
def numIslands(self, grid: List[List[str]]) -> int:
# 初始化岛屿数量为 0
count = 0
# 获取网格的行数和列数
m, n = len(grid), len(grid[0])
# 使用 deque(双端队列)来实现 BFS
queue = deque()
# 方向数组,用于访问当前点的四个方向
directions = [(-1, 0), (1, 0), (0, -1), (0, 1)]
# 遍历整个二维网格
for i in range(m):
for j in range(n):
# 当找到一个 '1'(陆地)时
if grid[i][j] == '1':
# 岛屿数量加 1
count += 1
# 标记该陆地为已访问,这里使用 '2'
grid[i][j] = '2'
# 将该陆地的坐标加入队列
queue.append((i, j))
# BFS 开始
while len(queue) > 0:
# 弹出一个点并访问其四周
x, y = queue.popleft()
# 遍历当前点的四个方向
for dx, dy in directions:
new_x, new_y = x + dx, y + dy
# 如果新点在网格内并且是陆地
if 0 <= new_x < m and 0 <= new_y < n and grid[new_x][new_y] == '1':
# 标记为已访问
grid[new_x][new_y] = '2'
# 将新点加入队列,以便进一步搜索
queue.append((new_x, new_y))
# 返回岛屿数量
return count
Leetcode 463. 岛屿的周长
题目描述
给定一个 row x col 的二维网格地图 grid ,其中:grid[i][j] = 1 表示陆地, grid[i][j] = 0 表示水域。
网格中的格子 水平和垂直 方向相连(对角线方向不相连)。整个网格被水完全包围,但其中恰好有一个岛屿(或者说,一个或多个表示陆地的格子相连组成的岛屿)。
岛屿中没有“湖”(“湖” 指水域在岛屿内部且不和岛屿周围的水相连)。格子是边长为 1 的正方形。网格为长方形,且宽度和高度均不超过 100 。计算这个岛屿的周长。
示例 1:
输入: grid = [[0,1,0,0],[1,1,1,0],[0,1,0,0],[1,1,0,0]]
输出: 16
解释: 它的周长是上面图片中的 16 个黄色的边
示例 2:
输入: grid = [[1]]
输出: 4
示例 3:
输入: grid = [[1,0]]
输出: 4
提示:
row == grid.lengthcol == grid[i].length1 <= row, col <= 100grid[i][j]为0或1
解法
直接遍历格子,如果它是陆地,则周长加上4,但同时,如果它的左边是陆地,那么会有一条公共边,周长减去2;同理如果它的上面是陆地,也要减去2。
完整代码如下:
class Solution:
def islandPerimeter(self, grid: List[List[int]]) -> int:
ans = 0
m, n = len(grid), len(grid[0])
for i in range(m):
for j in range(n):
if grid[i][j] == 1:
ans += 4
if i-1>=0 and grid[i-1][j]==1:
ans -= 2
if j-1>=0 and grid[i][j-1]==1:
ans -= 2
return ans