如何利用python的特点实现bfs和dfs
在dfs和bfs中,通常需要标记已经访问过的结点,一般的做法是建立一个vis数组,然后初始化全部为0,若访问过,则标记为1
但是在python中,我们可以利用defaultdic做标记
比如我们要对(1,2)这个点做标记,直接使用:
vis = defaultdict(bool)
vis[(i, j)] = True
这样就直接标记了,根本不需要生成一个很大的标记数组。
而使用列表和字典标记的时候,都需要先初始化,否则会报错。使用defaultdict则完全不用初始化key的值。
看看下面这个题目
题目
给定一个二维的矩阵,包含 ‘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’。**如果两个元素在水平或垂直方向相邻,则称它们是“相连”的。
思路
1.找到边界上为为“O”的点的位置,做dfs或者bfs,将与之连通的点标记成已经访问
2.遍历整个区域(除去边界),将没有访问过的“O”变为“X”
代码
from collections import defaultdict
from collections import deque
dx = [0,0,1,-1]
dy = [1,-1,0,0]
def isin(x, y, board):
if 0 <= x <= len(board) - 1 and 0 <= y <= len(board[0]) - 1:
return True
else:
return False
class Solution(object):
def solve(self, board):
if not board:
return
vis = defaultdict(bool)
for i in [0, len(board)-1]:
for j in range(len(board[0])):
if board[i][j] == "O" and not vis[(i, j)]:
vis[(i, j)] = True
queue = deque()
queue.append((i, j))
while queue:
x, y = queue.popleft()
for k in range(4):
tx = x + dx[k]
ty = y + dy[k]
if isin(tx, ty, board) and not vis[(tx, ty)] and board[tx][ty] == "O":
vis[(tx, ty)] = 1
queue.append((tx, ty))
for i in range(1, len(board)-1):
for j in [0, len(board[0]) - 1]:
if board[i][j] == "O" and not vis[(i, j)]:
vis[(i, j)] = 1
queue = deque()
queue.append((i, j))
while queue:
x, y = queue.popleft()
for k in range(4):
tx = x + dx[k]
ty = y + dy[k]
if isin(tx, ty, board) and not vis[(tx, ty)] and board[tx][ty] == "O":
vis[(tx, ty)] = 1
queue.append((tx, ty))
for i in range(1,len(board)-1):
for j in range(1, len(board[0])-1):
if board[i][j] == "O" and not vis[(i, j)]:
board[i][j] = "X"