题目描述:
给你一个由 ‘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
思路1:
通过染色法,若一个为1的区域是整个大区域的一部分将其值返回为0,一个岛屿的第一个1仍为1,其余为0,是一种扩散的思想。可以通过深搜和广搜两种方式实现。
DFS:以深度进行扩散
BFS:把结点放到一个queue里,取出一个把其相邻的四个中为1的加入队列中,直到整个队列为空。
深搜:
class Solution(object):
def numIslands(self, grid):
"""
:type grid: List[List[str]]
:rtype: int
"""
self.dx = [-1, 1, 0, 0]
self.dy = [0, 0, -1, 1]
self.grid = grid
self.visited = set()
m, n = len(grid), len(grid[0])
res = [[0 for _ in range(len(grid[0]))] for _ in range(len(grid))]
sum = 0
for i in range(m):
for j in range(n):
res[i][j] = self.DFS(i, j)
sum += res[i][j]
return sum
def DFS(self, i, j):
if not self.is_valid(i, j):
return 0
self.visited.add((i, j))
for k in range(4):
self.DFS(i+self.dx[k], j+self.dy[k])
return 1
def is_valid(self, i, j):
if i < 0 or j < 0 or i >= len(self.grid) or j >= len(self.grid[0]):
return False
if self.grid[i][j] == "0" or ((i, j) in self.visited):
return False
return True
广搜:
import collections
class Solution(object):
def numIslands(self, grid):
"""
:type grid: List[List[str]]
:rtype: int
"""
self.dx = [-1, 1, 0, 0]
self.dy = [0, 0, -1, 1]
self.grid = grid
self.visited = set()
m, n = len(grid), len(grid[0])
res = [[0 for _ in range(len(grid[0]))] for _ in range(len(grid))]
sum = 0
for i in range(m):
for j in range(n):
res[i][j] = self.BFS(i, j)
sum += res[i][j]
return sum
def BFS(self, i, j):
if not self.is_valid(i, j):
return 0
self.visited.add((i, j))
queue = collections.deque()
queue.append((i, j))
while queue:
x, y = queue.popleft()
for k in range(4):
nx, ny = x+self.dx[k], y+self.dy[k]
if self.is_valid(nx, ny):
queue.append((nx, ny))
self.visited.add((nx, ny))
return 1
思路2: 并查集
a. 初始化:所有为1的结点的根是自己
b. 遍历所有的结点,相邻的结点如为1进行合并根,为0时不需要进行操作,最后root是统计组的数量,可以在初始化和合并的过程中进行统计;如果采用最后进行一次遍历parent的话注意parent[0] = 0的处理。
class Solution(object):
def numIslands(self, grid):
"""
:type grid: List[List[str]]
:rtype: int
"""
if not grid or not grid[0]:
return 0
uf = UnionFind(grid)
h = len(grid)
l = len(grid[0])
dx = [-1, 1, 0, 0]
dy = [0, 0, -1, 1]
for i in range(h):
for j in range(l):
if grid[i][j] == "1":
for d in range(4):
nx, ny = i+dx[d], j+dy[d]
if 0 <= nx < h and 0 <= ny < l and grid[nx][ny] == "1":
uf.union(i * l + j, nx * l + ny)
return uf.count
class UnionFind(object):
def __init__(self, grid):
m = len(grid)
n = len(grid[0])
self.parent = [0] * (m*n)
self.rank = [0] * (m*n)
self.count = 0
for i in range(m):
for j in range(n):
if grid[i][j] == "1":
self.parent[i*n+j] = i*n+j
self.count += 1
def find(self, i):
while i != self.parent[i]:
i = self.parent[i]
return i
def union(self, x, y):
rootx = self.find(x)
rooty = self.find(y)
if rootx != rooty:
if self.rank[rootx] < self.rank[rooty]:
self.parent[rootx] = rooty
elif self.rank[rootx] > self. rank[rooty]:
self.parent[rooty] = rootx
else:
self.parent[rooty] = rootx
self.rank[rootx] += 1
self.count -= 1