深搜思想(DFS) 实现起来代码更简洁一点,但是不利于理解,深搜一般用到了递归结构,即在函数中不断调用自己(但函数的参数变量肯定会变);
宽搜思想(BFS) 符合人们的正常思维,但需要构建一个队列进行维护,不断取出队列头部元素并判断其周围元素。
拿岛屿问题来讲: 深搜每次扩展一个格子,宽搜每次扩展一层格子
但是根据我的做题经验来看,深搜能解决的问题比宽搜多的多,如二叉树,树形结构的问题(回溯法问题)都可以用深搜DFS解决,并且DFS照比BFS快得多
一、岛屿数量
from collections import deque
class Solution:
def numIslands(self, grid: List[List[str]]) -> int:
# 深搜实现起来代码简洁一点,但是不利于理解,宽搜思想符合人们的正常思维,但是需要构建一个数组进行维护,不断从头部取出元素判断其周围元素
# 深搜每次扩展一个格子
def dfs(grid, i, j):
# 如果此位置超出岛屿边界或者此位置不存在岛屿,则推出深搜
if not 0<= i < len(grid) or not 0<=j<len(grid[0]) or grid[i][j] == "0":
return # 退出深搜
grid[i][j]= '0' # 把搜索过的位置标记,避免重复记录
dfs(grid, i, j+1) # 右
dfs(grid, i+1, j) # 下
dfs(grid, i, j-1) # 左
dfs(grid, i-1, j) # 上
def bfs(grid, i, j):
# 构建队列
neighbors = deque([(i,j)])
# 如果队列非空
while neighbors:
# 找到此时位置
i,j = neighbors.popleft()
# 宽搜每次扩展一层格子
for x,y in [(i, j+1),(i+1, j),(i, j-1),(i-1, j)]: # 按照右上左下的顺序依次遍历
if 0<=x<len(grid) and 0<= y< len(grid[0]) and grid[x][y] == "1":
neighbors.append((x,y))
grid[x][y] = "0"
count = 0
for i in range(len(grid)):
for j in range(len(grid[0])):
if grid[i][j] == '1': # 找到岛屿中其中一个陆地的位置
# bfs(grid, i,j)
dfs(grid, i,j)
count +=1
return count
二、岛屿的最大面积
# 岛屿数量问题看好list里传入的是字符还是int
from collections import deque
class Solution:
def maxAreaOfIsland(self, grid: List[List[int]]) -> int:
# 在函数内部构建dfs bfs 函数
def dfs(grid, i,j):
if not 0<=i<len(grid) or not 0<=j<len(grid[0]) or grid[i][j] == 0:
return 0 # 退出dfs搜索
# 每次搜索时,都应该将count +=1
grid[i][j] = 0
count = 1
print(id(count))
for di,dj in [[0,1],[1,0],[0,-1], [-1,0]]:
next_i ,next_j = i+di, j+dj
count += dfs(grid, next_i, next_j)
# 返回的count是最终的结果
return count # 要把count返回回去,跟res比较哪个大
def bfs(grid,i,j):
neighbors = deque([(i,j)])
count = 0 # count是0还是1呢,应该是0,分析一下:此时的i和j符合一个陆地,
# 在后面的bfs中,会将这个位置搜索出来,此时只是将这个位置定位一个起点
while neighbors:
i,j = neighbors.popleft()
if not 0<=i<len(grid) or not 0<=j<len(grid[0]) or grid[i][j]==0:
#if i<0 or i== len(grid) or j<0 or j== len(grid[0]) or grid[i][j] == 0:
continue
count +=1
for x,y in [(i,j+1),(i+1,j),(i,j-1),(i-1,j)]:
neighbors.append((x,y))
return count
res = 0
for i in range(len(grid)):
for j in range(len(grid[0])):
if grid[i][j] == 1: # 找到陆地位置
# 实现dfs或者bfs
count = dfs(grid,i,j)
# count = bfs(grid,i,j)
res = max(res, count)
return res
三、岛屿的周长
from collections import deque
class Solution:
def islandPerimeter(self, grid: List[List[int]]) -> int:
def bfs(grid,i,j):
neighbors = deque([(i,j)])
count = 0
while neighbors:
i,j = neighbors.popleft()
# 避免重复统计
grid[i][j] = 2
for x,y in [(i,j+1),(i+1,j),(i,j-1),(i-1,j)]:
# 遇到边界或者水域,则周长加一
if x<0 or x>=len(grid) or y<0 or y>=len(grid[0]) or grid[x][y] ==0:
count +=1
# 相邻区域为陆地,则将其标记为2,加入队列
elif grid[x][y] == 1:
grid[x][y] = 2
neighbors.append((x,y))
# 相邻区域为已标记陆地,则不做处理
return count
def dfs(grid, i,j):
perimeter = 0
grid[i][j] = 2
for di,dj in [[0,1],[1,0],[0,-1], [-1,0]]:
next_i ,next_j = i+di, j+dj
if next_i<0 or next_i>=len(grid) or next_j<0 or next_j>=len(grid[0]) or grid[next_i][next_j] ==0:
perimeter+=1
elif grid[next_i][next_j] == 2:
continue
elif grid[next_i][next_j] == 1:
perimeter+=dfs(grid,next_i,next_j)
return perimeter
res = 0
for i in range(len(grid)):
for j in range(len(grid[0])):
if grid[i][j] == 1: # 找到陆地位置
# 实现dfs或者bfs
res += dfs(grid,i,j)
# count = bfs(grid,i,j)
# return count
return res