LeetCode 130. Surrounded Regions (并查集)
Tags:
- Breadth-first Search
- Union Find
问题描述
Given a 2D board containing ‘X’ and ‘O’ (the letter O), capture all regions surrounded by ‘X’.
A region is captured by flipping all ‘O’s into ‘X’s in that surrounded region.
For example,
X X X X
X O O X
X X O X
X O X X
After running your function, the board should be:
X X X X
X X X X
X X X X
X O X X
Subscribe to see which companies asked this question.
解题思路
题意是把所有不与边界直接相连的O变为X。
使用并查集,将所有相连的O转换为并查集并且相连。
然后定义一个虚节点,表示边界。
把与边界相连的结点和虚节点链接,表示该节点与边界相连,不需要变成X。
最后把不与虚节点连接的O结点变为X。
参考代码
#include <iostream>
#include <vector>
using namespace std;
class UF // union find
{
private:
int *id; // parent link
int *sz; // size of component for roots
int count; // number of components
public:
UF(int N)
{
count = N;
id = new int[N];
sz = new int[N];
for (int i = 0; i < N; ++i)
{
id[i] = i;
sz[i] = 1;
}
}
~UF()
{
delete[] id;
delete[] sz;
}
int getCount()
{
return count;
}
int find(int i)
{
while (i != id[i])
{
id[i] = id[id[i]]; // path compression by halving
i = id[i];
}
return i;
}
bool connected(int p, int q) // check if two union is connected
{
return find(p) == find(q);
}
void connect(int p, int q) // merge
{
int i = find(p);
int j = find(q);
if (i == j) return;
// make smaller root point to larger one
if(sz[i] < sz[j])
{
id[i] = j;
sz[j] += sz[i];
}
else
{
id[j] = i;
sz[i] += sz[j];
}
count--;
}
};
class Solution
{
public:
void solve(vector<vector<char>> &board)
{
int n = board.size();
if (n == 0)return;
int m = board[0].size();
UF uf = UF(n * m + 1); // n * m is a dummy node, which means boundary
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < m; ++j)
{
// if a 'O' node is on the boundary, connect it to the dummy node
if((i == 0 || i == n - 1 || j == 0 || j == m - 1) && board[i][j] == 'O')
{
uf.connect(i * m + j, n * m);
}
// connect a 'O' node to its neighbor 'O' nodes
else if (board[i][j] == 'O')
{
if (board[i - 1][j] == 'O')
uf.connect(i * m + j, (i - 1) * m + j);
if (board[i + 1][j] == 'O')
uf.connect(i * m + j, (i + 1) * m + j);
if (board[i][j - 1] == 'O')
uf.connect(i * m + j, i * m + j - 1);
if (board[i][j + 1] == 'O')
uf.connect(i * m + j, i * m + j + 1);
}
}
}
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < m; ++j)
{
// if a 'O' node is not connected to the dummy node, it is captured
if (!uf.connected(i * m + j, n * m))
{
board[i][j] = 'X';
}
}
}
}
};
int main()
{
vector<vector<char>> board =
{
{'X', 'X', 'X', 'X'},
{'X', 'O', 'O', 'X'} ,
{'X', 'X', 'O', 'X'},
{'X', 'O', 'X', 'X'}
};
auto sl = new Solution();
sl->solve(board);
for (auto a : board)
{
for (auto b : a)
{
cout << b << " ";
}
cout << endl;
}
system("pause");
return 0;
}