每日挑战(C++版)
在这里,我将开始每天练习LeetCode算法题,并将个人解决方案放在这里。
需求介绍
给你一个 的矩阵
board
,由若干字符 'X'
和 'O'
,找到所有被 'X'
围绕的区域,并将这些区域里所有的 'O'
用 'X'
填充。
被围绕的区间不会存在于边界上,换句话说,任何边界上的 'O' 都不会被填充为 'X'。 任何不在边界上,或不与边界上的 'O' 相连的 'O' 最终都会被填充为 'X'。如果两个元素在水平或垂直方向相邻,则称它们是“相连”的。
测试例题
- 实例1:
输入:board = [["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"]]
- 实例2:
输入:board = [["X"]]
输出:[["X"]]
个人分析
从第二段中描述中可以看出,任何边界上的 'O' 都不会被填充为 'X'。 任何不在边界上,或不与边界上的 'O' 相连的 'O' 最终都会被填充为 'X'。从这句话可以找到解题的思路,就是对边界上的'O'进行递归,将相连的'O'全部保存。在遍历完所有边界上的元素后,没有保存的'O'就被填充为'X'。
有了上述的解题思路后,就需要进行逻辑的设计。该题有个大前提就是需要在board上进行原地修改,而不是返回一个新的二维数组。
- 当二维数组的m或者n小于3时,无需进行判断,因为所有的节点均为边界。不需要对数组进行修改。
- 对边界上的'O'进行递归。需要对二维数组的第一行,最后一行,第一列,最后一列进行遍历判断。从坐标来看
第一行的坐标从board[0][0], board[0][1], ... board[0][n - 1]。
最后一行的坐标为board[m-1][0], board[m-1][1], ... board[m-1][n - 1]。
第一列的坐标从board[0][0], board[1][0], ... board[m-1][0]。
最后一列的坐标为board[0][n-1], board[0][n-1], ... board[0][n-1]。
若有相连的,只需要进行坐标变换,递归即可。 - 将相连的'O'全部保存。因为要在原数组上进行修改,如果直接在原数组上进行保存,那么无法删选出那些没有相连的'O'。因此需要在采用一个辅助的二维数组用来保存那些'O'是需要保存的。
- 最后通过对二维数组进行遍历,加上辅助二维数组的数据,即可完成对不相连'O'的填充。
代码实现
class Solution {
public:
void search(vector<vector<char>>& board, vector<vector<bool>>& flag, int i, int j, int m, int n)
{
// 上
if(i - 1 >= 0 && board[i - 1][j] == 'O' && !flag[i - 1][j])
{
flag[i - 1][j] = true;
search(board, flag, i - 1, j, m, n);
}
// 下
if(i + 1 < m && board[i + 1][j] == 'O' && !flag[i + 1][j])
{
flag[i + 1][j] = true;
search(board, flag, i + 1, j, m, n);
}// 左
if(j - 1 >= 0 && board[i][j - 1] == 'O' && !flag[i][j - 1])
{
flag[i][j - 1] = true;
search(board, flag, i, j - 1, m, n);
}// 右
if(j + 1 < n && board[i][j + 1] == 'O' && !flag[i][j + 1])
{
flag[i][j + 1] = true;
search(board, flag, i, j + 1, m, n);
}
}
void solve(vector<vector<char>>& board) {
int m = board.size();
int n = board[0].size();
vector<vector<bool>> flag(m, vector<bool>(n, false));
if(m > 2 && n > 2)
{
// 第一行和最后一行
for(int i = 0; i < n; i++)
{
if(board[0][i] == 'O')
{
flag[0][i] = true;
search(board, flag, 0, i, m, n);
}
if(board[m - 1][i] == 'O')
{
flag[m-1][i] = true;
search(board, flag, m - 1, i, m, n);
}
}
// 第一列和最后一列
for(int j = 0; j < m; j++)
{
if(board[j][0] == 'O')
{
flag[j][0] = true;
search(board, flag, j, 0, m, n);
}
if(board[j][n-1] == 'O')
{
flag[j][n-1] = true;
search(board, flag, j, n-1, m, n);
}
}
for(int i = 0; i < m; i++)
{
for(int j = 0; j < n; j++)
{
if(!flag[i][j] && board[i][j] == 'O')
{
board[i][j] = 'X';
}
}
}
}
}
};
总结
上诉代码在时间上超过了71.66%的用户,内存上超过了11.54%的用户。