给定一个二维的矩阵,包含 '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'
。如果两个元素在水平或垂直方向相邻,则称它们是“相连”的。
解题思路
这个问题,和之前的 Leetcode 79:单词搜索(最详细的解法!!!)、Leetcode 200:岛屿的个数(最详细的解法!!!)很类似。这个问题一个很简单的处理思路就是将外围的O
元素单独考虑。基于这个思路,我们将外围的O
替换为标记为*
。
X X X X
X O O X
X X O X
X * X X
然后我们就只要将图中的O
替换成X
,将*
替换成O
即可。这里有这样一种情况
X X X X
X O O X
X X O X
X O O X
这里的O
全部就外围元素。替换为*
,就变成了
X X X X
X * * X
X X * X
X * * X
所以我们现在的问题就变成了:在这个图的边界位置出发找连通的O
。这就和之前的问题联系在一起了。
class Solution:
def solve(self, board):
"""
:type board: List[List[str]]
:rtype: void Do not return anything, modify board in-place instead.
"""
if not board:
return None
m, n = len(board), len(board[0])
d = [(-1, 0), (0, 1), (1, 0), (0, -1)]
def _solve(i, j):
if 0 <= i < m and 0 <= j < n and board[i][j] == 'O':
board[i][j] = '*'
for k in range(4):
_solve(i + d[k][0], j + d[k][1])
for i in range(m):
_solve(i, 0)
_solve(i, n - 1)
for i in range(n):
_solve(0, i)
_solve(m - 1, i)
for i in range(m):
for j in range(n):
if board[i][j] == 'O':
board[i][j] = 'X'
elif board[i][j] == '*':
board[i][j] = 'O'
我们有一个更pythonic
的写法。
class Solution:
def solve(self, board):
"""
:type board: List[List[str]]
:rtype: void Do not return anything, modify board in-place instead.
"""
if not board:
return None
m, n = len(board), len(board[0])
def _solve(i, j):
if 0 <= i < m and 0 <= j < n and board[i][j] == 'O':
board[i][j] = '*'
list(map(_solve, (i+1, i-1, i, i), (j, j, j+1, j-1)))
for i in range(m):
list(map(_solve, (i, i), (0, n - 1)))
for i in range(n):
list(map(_solve, (0, m - 1), (i, i)))
for i in range(m):
for j in range(n):
if board[i][j] == 'O':
board[i][j] = 'X'
elif board[i][j] == '*':
board[i][j] = 'O'
要注意的是python3
中,map
函数返回的是一个iterator
,所以我们要通过list
将包在外面,去自动推导它。
同样的,对于递归解决的问题,我们都应该思考一下怎么通过迭代去解决。写法和Leetcode 200:岛屿的个数(最详细的解法!!!)问题中的迭代版本写法类似。
class Solution:
def solve(self, board):
"""
:type board: List[List[str]]
:rtype: void Do not return anything, modify board in-place instead.
"""
if not board:
return None
m, n = len(board), len(board[0])
def _solve(i, j):
if board[i][j] != 'O':
return
stack = list()
stack.append((i, j))
while stack:
x, y = stack.pop()
if board[x][y] != 'O':
continue
board[x][y] = '*'
directions = [(-1, 0), (0, 1), (1, 0), (0, -1)]
for d in directions:
nr = x + d[0]
nc = y + d[1]
if 0 <= nr < m and 0 <= nc < n:
stack.append((nr, nc))
for i in range(m):
list(map(_solve, (i, i), (0, n - 1)))
for i in range(n):
list(map(_solve, (0, m - 1), (i, i)))
for i in range(m):
for j in range(n):
if board[i][j] == 'O':
board[i][j] = 'X'
elif board[i][j] == '*':
board[i][j] = 'O'
我们将self._solve
写成一个迭代版本即可。
我将该问题的其他语言版本添加到了我的GitHub Leetcode
如有问题,希望大家指出!!!