classUnionFind:def__init__(self, n):
self._count = n
self.parent =[i for i inrange(n)]
self.size =[1for _ inrange(n)]for i inrange(n):
self.parent[i]= i
self.size[i]=1defunion(self, p, q):
root_p = self.find(p)
root_q = self.find(q)if root_q == root_p:return# 小树接到大树下面,较平衡if self.size[root_p]> self.size[root_q]:
self.parent[root_q]= root_p
self.size[root_p]+= self.size[root_q]else:
self.parent[root_p]= root_q
self.size[root_q]+= self.size[root_p]
self._count -=1deffind(self, x):while self.parent[x]!= x:
self.parent[x]= self.parent[self.parent[x]]
x = self.parent[x]return x
defconnected(self, p, q):
root_p = self.find(p)
root_q = self.find(q)return root_p == root_q
@propertydefcount(self):return self._count
【130. 被围绕的区域】
defconnectedArea(board):'''
给你⼀个 m x n 的矩阵 board,由若⼲字符 'X' 和 'O' 组成,找到所有被 'X' 围绕的区域,并将这些区域⾥所有的 'O' ⽤ 'X' 填充。
leetcode: 130. 被围绕的区域
input:board = [
["X","X","X","X"],
["X","O","O","X"],
["X","X","O","X"],
["X","O","X","X"]
]
output: [
["X","X","X","X"],
["X","X","X","X"],
["X","X","X","X"],
["X","O","X","X"]
]
被围绕的区间不会存在于边界上,换句话说,任何边界上的 'O' 都不会被填充为 'X'。
任何不在边界上,或不与边界上的 'O' 相连的 'O' 最终都会被填充为 'X'。
如果两个元素在⽔平或垂直⽅向相邻,则称它们是“相连”的
思路:
1.
2.
3.
'''iflen(board)==0:return0
m, n =len(board),len(board[0])
uf = UnionFind(m * n +1)
dummy = m * n
# 首列和末列的O与dummy相连for i inrange(m):if board[i][0]=="O":
uf.union(i * n, dummy)if board[i][n -1]=="O":
uf.union(i * n + n -1, dummy)# 首行和末行的O与dummy相连for j inrange(n):if board[0][j]=="O":
uf.union(j, dummy)if board[m -1][j]=="O":
uf.union(n *(m -1)+ j, dummy)
direct =[[1,0],[0,1],[0,-1],[-1,0]]for i inrange(1, m -1):for j inrange(1, n -1):if board[i][j]=="O":for k inrange(0,4):
x = i + direct[k][0]
y = j + direct[k][1]if board[x][y]=="O":
uf.union(x * n + y, i * n + j)for i inrange(1, m -1):for j inrange(1, n -1):ifnot uf.connected(dummy, i * n + j):
board[i][j]='X'for b in board:print(b)print('\n')
【200 岛屿数量】
defnumIslands(grid):'''
给你⼀个由 '1'(陆地)和 '0'(⽔)组成的的⼆维⽹格,请你计算⽹格中岛屿的数量。
岛屿总是被⽔包围,并且每座岛屿只能由⽔平⽅向和/或竖直⽅向上相邻的陆地连接形成。此外,你可以假设该⽹格的四条边均被⽔包围。
leetcode:200 岛屿数量
input:grid = [
["1","1","1","1","0"],
["1","1","0","1","0"],
["1","1","0","0","0"],
["0","0","0","0","0"]
]
output: 1
思路:
1.
2.
3.
'''
res =0
m, n =len(grid),len(grid[0])defdfs(_grid, i, j):
m, n =len(_grid),len(_grid[0])if i <0or j <0or i > m or j > n:returnif _grid[i][j]=='0':return
_grid[i][j]='0'
dfs(_grid, i +1, j)
dfs(_grid, i, j +1)
dfs(_grid, i -1, j)
dfs(_grid, i, j -1)for i inrange(m):for j inrange(n):if grid[i][j]=='1':
res +=1
dfs(grid, i, j)for g in grid:print(g)print(res)
【 1254 统计封闭岛屿的数目】
defclosedIsland(grid):'''
有一个二维矩阵 grid ,每个位置要么是陆地(记号为 0 )要么是水域(记号为 1 )。
我们从一块陆地出发,每次可以往上下左右 4 个方向相邻区域走,能走到的所有陆地区域,我们将其称为一座「岛屿」。
如果一座岛屿 完全 由水域包围,即陆地边缘上下左右所有相邻区域都是水域,那么我们将其称为 「封闭岛屿」。
请返回封闭岛屿的数目。其中0是陆地,1是海水。
leetcode: 1254 统计封闭岛屿的数目
input:grid = [
[1,1,1,1,1,1,1,0],
[1,0,0,0,0,1,1,0],
[1,0,1,0,1,1,1,0],
[1,0,0,0,0,1,0,1],
[1,1,1,1,1,1,1,0]
]
output:2
思路:
1.
2.
3.
'''
m, n =len(grid),len(grid[0])# m行 n列defdfs(_grid, i, j):
m, n =len(_grid),len(_grid[0])if i >= m or j >= n or i <0or j <0:returnif _grid[i][j]==1:# 1代表海水,已经被淹没过了return
_grid[i][j]=1
dfs(_grid, i +1, j)
dfs(_grid, i, j +1)
dfs(_grid, i -1, j)
dfs(_grid, i, j -1)# 将首行和末行淹没for i inrange(n):
dfs(grid,0, i)
dfs(grid, m -1, i)# 将首列和末列淹没for i inrange(m):
dfs(grid, i,0)
dfs(grid, i, n -1)
res =0for i inrange(m):for j inrange(n):if grid[i][j]==0:
res +=1
dfs(grid, i, j)for g in grid:print(g)print(res)return res
【1020 飞地的数量】
defnumEnclaves(grid):'''
给出一个二维数组 A,每个单元格为 0(代表海)或 1(代表陆地)。
移动是指在陆地上从一个地方走到另一个地方(朝四个方向之一)或离开网格的边界。
返回网格中无法在任意次数的移动中离开网格边界的陆地单元格的数量。 1代表陆地,0代表海洋
leetcode: 1020 飞地的数量
input: [
[0,0,0,0],
[1,0,1,0],
[0,1,1,0],
[0,0,0,0]
]
output: 3
思路:
1.
2.
3.
'''
m, n =len(grid),len(grid[0])
res =0defdfs(_grid, i, j):
m, n =len(grid),len(grid[0])if i <0or j <0or i >= m or j >= n:returnif _grid[i][j]==0:return
_grid[i][j]=0
dfs(_grid, i +1, j)
dfs(_grid, i, j +1)
dfs(_grid, i -1, j)
dfs(_grid, i, j -1)for i inrange(m):
dfs(grid, i,0)
dfs(grid, i, n -1)for i inrange(n):
dfs(grid,0, i)
dfs(grid, m -1, i)for i inrange(m):for j inrange(n):if grid[i][j]==1:
res +=1print(res)return res
【 695 岛屿的最大面积】
defmaxAreaOfIsland(grid):'''
给定一个包含了一些 0 和 1的非空二维数组 grid , 一个 岛屿 是由四个方向 (水平或垂直) 的 1 (代表土地) 构成的组合。
你可以假设二维矩阵的四个边缘都被水包围着。
找到给定的二维数组中最大的岛屿面积。(如果没有岛屿,则返回面积为0。) 0表示海水,1表示陆地
leetcode: 695 岛屿的最大面积
input:
[
[0,0,1,0,0,0,0,1,0,0,0,0,0],
[0,0,0,0,0,0,0,1,1,1,0,0,0],
[0,1,1,0,1,0,0,0,0,0,0,0,0],
[0,1,0,0,1,1,0,0,1,0,1,0,0],
[0,1,0,0,1,1,0,0,1,1,1,0,0],
[0,0,0,0,0,0,0,0,0,0,1,0,0],
[0,0,0,0,0,0,0,1,1,1,0,0,0],
[0,0,0,0,0,0,0,1,1,0,0,0,0]
]
output: 6
思路:
1.
2.
3.
'''
res =0
m, n =len(grid),len(grid[0])defdfs(_grid, i, j):
m, n =len(_grid),len(_grid[0])if i <0or j <0or i >= m or j >= n:return0if _grid[i][j]==0:return0
_grid[i][j]=0# 返回陆地面积return dfs(_grid, i +1, j)+ \
dfs(_grid, i, j +1)+ \
dfs(_grid, i -1, j)+ \
dfs(_grid, i, j -1)+1for i inrange(m):for j inrange(n):if grid[i][j]==1:# 淹没岛屿,并更新最大岛屿面积
res =max(res, dfs(grid, i, j))print(res)return res
【1905 统计子岛屿】
defcountSubIslands(grid1, grid2):'''
给你两个m x n的二进制矩阵grid1和grid2,它们只包含0(表示水域)和1(表示陆地)。一个岛屿是由四个方向(水平或者竖直)上相邻的1组成的区域。任何矩阵以外的区域都视为水域。
如果grid2的一个岛屿,被grid1的一个岛屿完全包含,也就是说grid2中该岛屿的每一个格子都被grid1中同一个岛屿完全包含,那么我们称grid2中的这个岛屿为子岛屿。
请你返回grid2中子岛屿的数目。0表示海水,1表示陆地
leetcode: 1905 统计子岛屿
input: grid1 = [
[1,1,1,0,0],
[0,1,1,1,1],
[0,0,0,0,0],
[1,0,0,0,0],
[1,1,0,1,1]
],
grid2 = [
[1,1,1,0,0],
[0,0,1,1,1],
[0,1,0,0,0],
[1,0,1,1,0],
[0,1,0,1,0]
]
output: 3
思路:
1. 如果岛屿B中存在一片陆地,在岛屿A的对应位置是海水,那么岛屿B就不是岛屿A的子岛。
2. 遍历grid2中的所有岛屿,把那些不可能是子岛的岛屿排除掉,剩下的就是子岛
3.
'''
m, n =len(grid1),len(grid1[0])
res =0defdfs(_grid, i, j):
m, n =len(_grid),len(_grid[0])if i <0or j <0or i >= m or j >= n:returnif _grid[i][j]==0:return
_grid[i][j]=0
dfs(_grid, i +1, j)
dfs(_grid, i, j +1)
dfs(_grid, i -1, j)
dfs(_grid, i, j -1)for i inrange(m):for j inrange(n):if grid1[i][j]==0and grid2[i][j]==1:# grid1中是海水,grid2中是陆地的部分,淹没
dfs(grid2, i, j)for i inrange(m):for j inrange(n):if grid2[i][j]==1:# grid2中是海水的部分
res +=1
dfs(grid2, i, j)print(res)return res
【694 不同的岛屿数量】
defnumDistinctIslands(grid):'''
给定一个非空0 1二维数组表示的网格,一个岛屿由四连通(上、下、左、右四个方向)的 1 组成,你可以认为网格的四周被海水包围。
请你计算这个网格中共有多少个形状不同的岛屿。两个岛屿被认为是相同的,当且仅当一个岛屿可以通过平移变换(不可以旋转、翻转)和另一个岛屿重合。
leetcode: 694 不同的岛屿数量
input:
output:
思路:
1.
2.
3.
'''
m, n =len(grid),len(grid[0])
islands =set()defdfs(_grid, i, j, _s, _dir):
m, n =len(_grid),len(_grid[0])if i <0or j <0or i >= m or j >= n or _grid[i][j]==0:return
_grid[i][j]=0
_s.append(_dir)
dfs(_grid, i -1, j, _s,1)
dfs(_grid, i +1, j, _s,2)
dfs(_grid, i, j -1, _s,3)
dfs(_grid, i, j +1, _s,4)
_s.append(-_dir)for i inrange(m):for j inrange(n):if grid[i][j]==1:
s =[]
dfs(grid, i, j, s,11)# print(s)
news =",".join([str(_)for _ in s])print(news)
islands.add(news)print(len(islands))returnlen(islands)