岛屿数量
题目描述:给你一个由 ‘1’(陆地)和 ‘0’(水)组成的的二维网格,请你计算网格中岛屿的数量。
岛屿总是被水包围,并且每座岛屿只能由水平方向或竖直方向上相邻的陆地连接形成。
此外,你可以假设该网格的四条边均被水包围。
输入:
11000
11000
00100
00011
输出: 3
解释: 每座岛屿只能由水平和/或竖直方向上相邻的陆地连接而成
基本思路:深度优先搜索,遍历矩阵中所有为1的网格,然后dfs,这里将访问过的节点做标记,防止再次访问。
代码如下:
class Solution:
directions = [(-1,0),(0,1),(1,0),(0,-1)]
def numIslands(self, grid: List[List[str]]) -> int:
m = len(grid)
if m==0:return 0
n = len(grid[0])
marked = [[False for _ in range(n)]for _ in range(m)]
count = 0
for i in range(m):
for j in range(n):
if not marked[i][j] and grid[i][j]=="1":
self.dfs(grid,i,j,m,n,marked)
count += 1
return count
def dfs(self,grid,i,j,m,n,marked):
marked[i][j]=True
for direction in self.directions:
new_i = i+ direction[0]
new_j = j+ direction[1]
if 0<=new_i<m and 0<=new_j<n and not marked[new_i][new_j] and grid[new_i][new_j]=="1":
self.dfs(grid,new_i,new_j,m,n,marked)
岛屿的最大面积
题目描述:给定一个包含了一些 0 和 1 的非空二维数组 grid 。
一个 岛屿 是由一些相邻的 1 (代表土地) 构成的组合,这里的「相邻」要求两个 1 必须在水平或者竖直方向上相邻。你可以假设 grid 的四个边缘都被 0(代表水)包围着。
找到给定的二维数组中最大的岛屿面积。(如果没有岛屿,则返回面积为 0 。)
基本思路:深度优先搜索,遍历每个岛屿,遇到1就将面积++,且将此位置标记,防止再次被访问。
代码如下:、
class Solution:
def dfs(self, grid, cur_i, cur_j):
if cur_i < 0 or cur_j < 0 or cur_i == len(grid) or cur_j == len(grid[0]) or grid[cur_i][cur_j] != 1:
return 0
grid[cur_i][cur_j] = 0
ans = 1
for di, dj in [[0, 1], [0, -1], [1, 0], [-1, 0]]:
next_i, next_j = cur_i + di, cur_j + dj
ans += self.dfs(grid, next_i, next_j)
return ans
def maxAreaOfIsland(self, grid: List[List[int]]) -> int:
ans = 0
for i, l in enumerate(grid):
for j, n in enumerate(l):
if grid[i][j]==1:
ans = max(self.dfs(grid, i, j), ans)
return ans
岛屿周长
题目描述:给定一个包含 0 和 1 的二维网格地图,其中 1 表示陆地 0 表示水域。
网格中的格子水平和垂直方向相连(对角线方向不相连)。整个网格被水完全包围,但其中恰好有一个岛屿(或者说,一个或多个表示陆地的格子相连组成的岛屿)。
岛屿中没有“湖”(“湖” 指水域在岛屿内部且不和岛屿周围的水相连)。格子是边长为 1 的正方形。网格为长方形,且宽度和高度均不超过 100 。计算这个岛屿的周长。
基本思路:直接遍历数组,如果当前位置为1,然后查看其上下左右四个方向的位置,如果不在矩阵中或者为0,就将周长加1.
class Solution:
def islandPerimeter(self, grid: List[List[int]]) -> int:
dir = [[1,0],[0,1],[-1,0],[0,1]]
perimeter = 0
for i in range(len(grid)):
for j in range(len(grid[0])):
if grid[i][j]==1:
for v in dir:
idx, idy = i+v[0], j+v[1]
if idx<0 or idx>=len(grid) or idy<0 or idy>=len(grid[0]):
perimeter += 1
else:
if grid[idx][idy]==0:perimeter+=1
return perimeter在这里插入代码片
统计封闭岛屿的数目
题目描述:有一个二维矩阵 grid ,每个位置要么是陆地(记号为 0 )要么是水域(记号为 1 )。
我们从一块陆地出发,每次可以往上下左右 4 个方向相邻区域走,能走到的所有陆地区域,我们将其称为一座「岛屿」。
如果一座岛屿 完全 由水域包围,即陆地边缘上下左右所有相邻区域都是水域,那么我们将其称为 「封闭岛屿」。
请返回封闭岛屿的数目。
基本思路:这里与之前不同的是,要求返回的是封闭岛屿的数量,封闭岛屿是岛屿上每个点都不在边界上,所以这里我们在dfs中判断岛屿是否有点在边界上。
代码如下:
class Solution:
def closedIsland(self, grid: List[List[int]]) -> int:
m, n = len(grid), len(grid[0])
count = 0
for i in range(m):
for j in range(n):
if grid[i][j]==0:
if not self.dfs(grid,i,j,m,n):count += 1
return count
def dfs(self,grid,i,j,m,n):
if i<0 or i==m or j<0 or j==n:
return True
if grid[i][j]!=0:
return False
grid[i][j] = 2
dir1 = self.dfs(grid,i+1,j,m,n)
dir2 = self.dfs(grid,i,j+1,m,n)
dir3 = self.dfs(grid,i-1,j,m,n)
dir4 = self.dfs(grid,i,j-1,m,n)
return dir1 or dir2 or dir3 or dir4
最大人工岛
题目描述:在二维地图上, 0代表海洋, 1代表陆地,我们最多只能将一格 0 海洋变成 1变成陆地。
进行填海之后,地图上最大的岛屿面积是多少?(上、下、左、右四个方向相连的 1 可形成岛屿)
基本思路:(1)我们依次将地图中海洋的位置变成陆地,然后在这张地图上寻找岛屿面积最大的
(2)用dfs遍历一遍地图,记录每个岛屿的面积,不同的岛屿用不同的标记,且记录该标记对应岛屿的面积。
在遍历一遍地图,对于海洋的位置,寻找其上下左右四个方向的不同岛屿将其面积相加,其中海洋可以看做面积为0的岛屿。
代码如下:
class Solution:
def largestIsland(self, grid: List[List[int]]) -> int:
ans = 0
maxv = 0
color = 2
dict = {}
dict[0]=0
for i, l in enumerate(grid):
for j, n in enumerate(l):
if grid[i][j]==1:
ans = self.dfs(grid, i, j,color)
maxv = max(ans,maxv)
dict[color] = ans
ans = 0
color += 1
for i in range(len(grid)):
for j in range(len(grid[0])):
if grid[i][j]==0:
count = 0
p =set()
for v in [[0, 1], [0, -1], [1, 0], [-1, 0]]:
around_i, around_j = i+v[0], j+v[1]
if 0<=around_i<len(grid) and 0<=around_j<len(grid[0]):
p.add(grid[around_i][around_j])
for k in p:
count += dict[k]
maxv = max(count + 1, maxv)
return maxv
def dfs(self, grid, cur_i, cur_j,color):
if cur_i < 0 or cur_j < 0 or cur_i == len(grid) or cur_j == len(grid[0]) or grid[cur_i][cur_j] != 1:
return 0
grid[cur_i][cur_j] = color
ans = 1
for di, dj in [[0, 1], [0, -1], [1, 0], [-1, 0]]:
next_i, next_j = cur_i + di, cur_j + dj
ans += self.dfs(grid, next_i, next_j,color)
return ans
被围绕的区域
给定一个二维的矩阵,包含 ‘X’ 和 ‘O’(字母 O)。
找到所有被 ‘X’ 围绕的区域,并将这些区域里所有的 ‘O’ 用 ‘X’ 填充。
示例:
X X X X
X O O X
X X O X
X O X X
运行你的函数后,矩阵变为:
X X X X
X X X X
X X X X
X O X X
解释:
被围绕的区间不会存在于边界上,换句话说,任何边界上的 ‘O’ 都不会被填充为 ‘X’。 任何不在边界上,或不与边界上的 ‘O’ 相连的 ‘O’ 最终都会被填充为 ‘X’。如果两个元素在水平或垂直方向相邻,则称它们是“相连”的。
基本思路:被围绕的区域为“O”且不与其他在边界上的“O”相连,反过来,我们先找到在边界的“O”,然后将其及与它相邻的“O”做标记“A”,然后遍历矩阵将剩下的“O”替换成“X”,再遍历矩阵将“A”替换会“O”
class Solution:
def dfs(self,board,i,j,m,n):
if i<0 or i==m or j<0 or j==n:
return
if board[i][j]!="O":
return
board[i][j]="A"
dir1 = self.dfs(board,i+1,j,m,n)
dir2 = self.dfs(board,i,j+1,m,n)
dir3 = self.dfs(board,i-1,j,m,n)
dir4 = self.dfs(board,i,j-1,m,n)
return dir1 or dir2 or dir3 or dir4
def solve(self, board: List[List[str]]) -> None:
"""
Do not return anything, modify board in-place instead.
"""
if not board:return board
m, n = len(board), len(board[0])
for i in range(m):
for j in range(n):
if board[i][j]=="O" and (i==0 or i==m-1 or j==0 or j==n-1):
self.dfs(board,i,j,m,n)
for i in range(m):
for j in range(n):
if board[i][j]=="O":board[i][j]="X"
for i in range(m):
for j in range(n):
if board[i][j]=="A":board[i][j]="O"