トピックリンク
タイトル説明:
'X'と 'O'(文字O)を含む2次元行列が与えられます。
「X」で囲まれたすべての領域を見つけ、これらの領域のすべての「O」を「X」で埋めます。
例:
XXXX
XOOX
XXOX
XOXX
関数を実行すると、行列は次のようになります。
XXXX
XXXX
XXXX
XOXX
説明:
境界に囲まれた間隔は存在しません。つまり、どの境界'O'
も塗りつぶされません'X'
。境界上ではなく、境界上にあるか、'O'
接続されていないため、'O'
最終的に塗りつぶされ'X'
ます。2つの要素が水平方向または垂直方向に隣接している場合、それらは「接続されている」と言われます。
問題解決のアイデア
質問を注意深く読むために、質問は実際には1つの文に簡略化できます:境界Oの接続された領域を見つけます。率直に言って、境界にOがあるかどうかを判断することです。ある場合、この点Oから4方向に広がります。Xと出会うか、別の境界に到達するまで、その方向のOを変更することはできません。
最初は、ダブルループトラバーサルの4方向のOを、ノードの内部ノード(つまり、の境界)に属していても、これらの4方向のOを無視して、直接見つけたいと思っていました。トラバーサルノードはすべての方向でXです)、ただし、必ずしもそれ自体の方向の内部ノードに属しているとは限らず、結果はテストケース31に該当します。
後で、問題解決領域の偉大な神々に触発されて、最初に境界がOである位置を見つけ、次にDFSが4方向でOの接続領域を見つけ、その領域の値をFに設定します(XとO以外の任意の値を使用できます。)残りのOは内部ノードである必要があり、最終的な二重ループの削減で十分です。
コード
class Solution {
public:
void solve(vector<vector<char>>& board) {
if(board.size() <= 2)
return;
int row = board.size(), line = board[0].size();
for(int i = 0; i < row; i++){
for(int j = 0; j < line; j++){
bool flag = i == 0 || i == row - 1 || j == 0 || j == line - 1;
if(flag && board[i][j] == 'O')
helper(board, i, j);
}
}
for(int i = 0; i < row; i++){
for(int j = 0; j < line; j++){
if(board[i][j] == 'O')
board[i][j] = 'X';
else if(board[i][j] == 'F')
board[i][j] = 'O';
}
}
return;
}
private:
void helper(vector<vector<char>>& board, int i, int j){
if(i < 0 || i >= board.size() || j < 0 || j >= board[0].size() || board[i][j] == 'X' || board[i][j] == 'F')
return;
board[i][j] = 'F';
helper(board, i - 1, j);
helper(board, i + 1, j);
helper(board, i, j - 1);
helper(board, i, j + 1);
return;
}
};
間違いや厳しくない場合は訂正してください、ありがとうございます。
私のブログ:http://breadhunter.gitee.io