题目描述
这道题考察的是图上的搜索问题,通用的策略是深度优先搜索 DFS和广度优先搜索 BFS。题目中解释说被包围的区间不会存在于边界上,所以我们可以考虑对处于边界上或者连通边界的 O 进行特殊处理,那么剩下的 O 就是不在边界上或者不与边界上的 O 相连的 O,将它们替换成 X 就可以了。具体来说,我们可以先对连通边界的 O 替换成其它字符(比如 B),然后遍历整个图把剩下的没被替换的 O 替换成 X,再把所有的 B 变回 O。
因此,问题转化为:如何寻找和边界联通的 O?
解法一:DFS
从边界出发,对图进行深度优先搜索。只要在边界上找到 O,我们就继续判断它的相邻位置(上下左右)是否还是 O,这样就可以找出所有连通边界的 O了。
class Solution(object):
def solve(self, board):
"""
:type board: List[List[str]]
:rtype: None Do not return anything, modify board in-place instead.
"""
if not board: return # 如果是空数组,直接返回
self.rows = len(board) # 行数
self.cols = len(board[0]) # 列数
if self.rows < 3 or self.cols < 3: return # 只有3X3及以上的矩阵才有可能出现被包围的‘o’
# 遍历边界上是否存在‘o’
for c in range(self.cols): # 遍历第一行和最后一行
self.dfs(board, 0, c)
self.dfs(board, self.rows-1, c)
for r in range(self.rows): # 遍历第一列和最后一列
self.dfs(board, r, 0)
self.dfs(board, r, self.cols-1)
# 最后遍历整个二维矩阵,把将所有的‘#’改回‘o’,将所有的‘o’改为‘x’
for i in range(self.rows):
for j in range(self.cols):
if board[i][j] == 'O':
board[i][j] = 'X'
elif board[i][j] == '#':
board[i][j] = 'O'
#---定义dfs递归函数---
def dfs(self, board, i, j): # 判断第 i行第 j列上是否为‘o’
# 递归base case
if i<0 or i>self.rows-1 or j<0 or j> self.cols-1 or board[i][j] != 'O': # 索引超出边界或当前位置不为‘o’,则不继续搜索
return
# 否则说明当前位置为‘o’,替换为‘#’
board[i][j] = '#'
# 递归判断当前位置的上下左右是否也为‘o’
self.dfs(board, i-1, j) # 上
self.dfs(board, i+1, j) # 下
self.dfs(board, i, j-1) # 左
self.dfs(board, i, j+1) # 右
解法二:BFS
广度优先搜索一般借助队列来实现。
class Solution(object):
def solve(self, board):
"""
:type board: List[List[str]]
:rtype: None Do not return anything, modify board in-place instead.
"""
if not board: return # 如果是空数组,直接返回
self.rows = len(board) # 行数
self.cols = len(board[0]) # 列数
if self.rows < 3 or self.cols < 3: return # 只有3X3及以上的矩阵才有可能出现被包围的‘o’
# 遍历边界上是否存在‘o’
for c in range(self.cols): # 遍历第一行和最后一行
self.bfs(board, 0, c)
self.bfs(board, self.rows-1, c)
for r in range(self.rows): # 遍历第一列和最后一列
self.bfs(board, r, 0)
self.bfs(board, r, self.cols-1)
# 最后遍历整个二维矩阵,把将所有的‘#’改回‘o’,将所有的‘o’改为‘x’
for i in range(self.rows):
for j in range(self.cols):
if board[i][j] == 'O':
board[i][j] = 'X'
elif board[i][j] == '#':
board[i][j] = 'O'
#---定义bfs函数---
def bfs(self, board, i, j): # 判断第 i行第 j列上是否为‘o’
queue = [] # 申请一个空队列
queue.append((i,j)) # 先把第 i行第 j列的位置入队
while queue:
i, j = queue.pop(0) # 弹出队首存储的位置进行判断
if i<0 or i>self.rows-1 or j<0 or j> self.cols-1 or board[i][j] != 'O' : # 若索引超出边界或当前位置不为‘O’,则不做任何处理,跳过当前循环
continue
# 否则,说明当前位置为‘O’,替换为‘#’
board[i][j] = '#'
# 将当前位置的上下左右的位置入队
queue.append((i-1,j))
queue.append((i+1,j))
queue.append((i,j-1))
queue.append((i,j+1))
最后,如果大家有更好的Python解法,欢迎在评论区分享下您的解法,一起进步,感谢^ o ^~