难度:中等
给定一个二维的矩阵,包含 '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'
。如果两个元素在水平或垂直方向相邻,则称它们是“相连”的。
题目分析:
正面思考,统计被包围的‘O’,明显很难统计,那么逆向思维,考虑从四条边上出发向里面进行深度搜索,看有哪些'O'是链接到边上的,是不会变成‘X’的,做好标记,那么剩余的‘O’就是被包围的,会变成‘X’的。这里我们使用DFS由边向里搜索。我们可以这么想,由边向里面搜索,遇到O就标记成#,接着搜索,遇到X或者#就说明碰壁了,这条路不同,直到四个方向都碰壁位置,就搜索完了,四条边依次进行DFS搜索。最后遍历所有元素,我们把剩余的‘O’变成‘X’,把#还原成O。
参考代码:
#include <iostream>
#include <vector>
#include <string>
#include <unordered_map>
#include <deque>
#include <stack>
#include <algorithm>
#include <map>
#include <assert.h>
#include <memory>
#include<queue>
#include<functional>
#include <set>
#include <unordered_set>
using namespace std;
class Solution {
public:
void solve(vector<vector<char>>& board) {
if (board.empty() || board[0].empty())
return;
//上下两层探索
for (int i = 0; i < board[0].size(); i++)
{
if (board[0][i] == 'O')
dfs(board,0,i);
if (board[board[0].size()-1][i] == 'O')
dfs(board, board[0].size() - 1, i);
}
//左右两列探索
for (int i = 1; i < board.size()-1; i++)
{
if (board[i][0] == 'O')
dfs(board, i, 0);
if (board[i][board.size() - 1] == 'O')
dfs(board, i, board.size() - 1);
}
//遍历所有元素把剩余的‘O’变成‘X’,把#还原成O
for (int i = 0; i < board.size(); i++)
{
for (int j = 0; j < board[0].size(); j++)
{
if (board[i][j] == 'O')
board[i][j] = 'X';
if (board[i][j] == '#')
board[i][j] = 'O';
cout << board[i][j] << " ";
}
cout << endl;
}
}
void dfs(vector<vector<char>>& board, int i, int j)
{
//边界及结束条件
if (i >= board.size() || i < 0 || j >= board[0].size() || j < 0 || board[i][j] == 'X' || board[i][j] == '#')
{
return;
}
board[i][j] = '#';
dfs(board, i + 1, j);
dfs(board, i - 1, j);
dfs(board, i, j + 1);
dfs(board, i, j - 1);
}
};
int main()
{
Solution solution;
vector<vector<char>> board = { { 'X', 'X', 'X', 'X' },
{ 'X', 'O', 'O', 'X' },
{ 'X', 'X', 'O', 'X' },
{ 'X', 'O', 'X', 'X' } };
solution.solve(board);
system("pause");
return 0;
}