给你一个 m x n 的矩阵 board ,由若干字符 ‘X’ 和 ‘O’ ,找到所有被 ‘X’ 围绕的区域,并将这些区域里所有的 ‘O’ 用 ‘X’ 填充。
正面dfs遍历
struct SimplePairHash {
std::size_t operator()(const std::pair<int, int>& p) const {
return ((p.first) << 16) | p.second;
}
};
class Solution {
public:
vector<vector<int>> visited; // 0表示未访问,1表示已访问
int row, col;
bool flag;
vector<vector<int>> dir = {{1, -1, 0, 0},{0, 0, 1, -1}};
void dfs(vector<vector<char>>& board, int i, int j, unordered_set<pair<int, int>, SimplePairHash>& us) {
visited[i][j] = 1;
us.insert(make_pair(i, j));
if((i == 0) || (i == row - 1) || (j == 0) || (j == col - 1))
flag = true;
for (int d = 0; d < dir[0].size(); d++) {
int new_i = i+dir[0][d];
int new_j = j+dir[1][d];
if (new_i >= 0 && new_i < row && new_j >= 0 && new_j < col &&
visited[new_i][new_j] == 0 && board[new_i][new_j] != 'X') {
dfs(board, new_i, new_j, us);
}
}
}
void solve(vector<vector<char>>& board) {
row = board.size();
col = board[0].size();
visited.resize(row);
for(int i = 0; i < row; i++) {
visited[i].resize(col, 0);
}
unordered_set<pair<int, int>, SimplePairHash> us;
unordered_set<pair<int, int>, SimplePairHash>::iterator usit;
for(int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
if (board[i][j] != 'X' && visited[i][j] == 0) {
flag = false;
dfs(board, i, j, us);
if (!flag) {
usit = us.begin();
while(usit != us.end()) {
board[usit->first][usit->second] = 'X';
usit++;
}
}
}
us.clear();
}
}
}
};
参考 https://leetcode-cn.com/problems/surrounded-regions/solution/bei-wei-rao-de-qu-yu-by-leetcode-solution/
外围dfs渗透
// 直接在原来的基础上改
class Solution {
public:
int n, m;
void dfs(vector<vector<char>>& board, int x, int y) {
if (x < 0 || x >= n || y < 0 || y >= m || board[x][y] != 'O') {
return;
}
board[x][y] = 'A';
dfs(board, x + 1, y);
dfs(board, x - 1, y);
dfs(board, x, y + 1);
dfs(board, x, y - 1);
}
void solve(vector<vector<char>>& board) {
n = board.size();
if (n == 0) {
return;
}
m = board[0].size();
for (int i = 0; i < n; i++) {
dfs(board, i, 0);
dfs(board, i, m - 1);
}
for (int i = 1; i < m - 1; i++) {
dfs(board, 0, i);
dfs(board, n - 1, i);
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (board[i][j] == 'A') {
board[i][j] = 'O';
} else if (board[i][j] == 'O') {
board[i][j] = 'X';
}
}
}
}
};
外围bfs渗透
class Solution {
public:
const int dx[4] = {1, -1, 0, 0};
const int dy[4] = {0, 0, 1, -1};
void solve(vector<vector<char>>& board) {
int n = board.size();
if (n == 0) {
return;
}
int m = board[0].size();
queue<pair<int, int>> que;
for (int i = 0; i < n; i++) {
if (board[i][0] == 'O') {
que.emplace(i, 0);
board[i][0] = 'A';
}
if (board[i][m - 1] == 'O') {
que.emplace(i, m - 1);
board[i][m - 1] = 'A';
}
}
for (int i = 1; i < m - 1; i++) {
if (board[0][i] == 'O') {
que.emplace(0, i);
board[0][i] = 'A';
}
if (board[n - 1][i] == 'O') {
que.emplace(n - 1, i);
board[n - 1][i] = 'A';
}
}
while (!que.empty()) {
int x = que.front().first, y = que.front().second;
que.pop();
for (int i = 0; i < 4; i++) {
int mx = x + dx[i], my = y + dy[i];
if (mx < 0 || my < 0 || mx >= n || my >= m || board[mx][my] != 'O') {
continue;
}
que.emplace(mx, my);
board[mx][my] = 'A';
}
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (board[i][j] == 'A') {
board[i][j] = 'O';
} else if (board[i][j] == 'O') {
board[i][j] = 'X';
}
}
}
}
};
附录 unordered_set 构造 pair<int, int>
Line 4: Char 32: note: default constructor of ‘Solution’ is implicitly deleted because field ‘us’ has a deleted default constructor
unordered_set<pair<int, int>> us;
参考:https://blog.csdn.net/weixin_44966641/article/details/121536027
C++中的unordered_map和unordered_set不能直接以pair作为键名的问题
在 C++ STL 中,不同于有序的 std::map 和 std::set 是基于红黑树实现的,
std::unordered_map 和 std::unordered_set 是基于哈希实现的,
在不要求容器内的键有序,仅要求查找效率较高时,哈希实现的后者时更为合适的。
既然是基于哈希实现的,那么就需要指定哈希函数。
对于内置的数据类型如 int,float,char 等,STL 库已经内置了常用的哈希函数。
因此在使用这些数据类型组成的 unordered_map 和 unordered_set 可以不再指定哈希函数,
直接默认。
unordered_map 的类模板定义:
template < class Key, //容器中存储元素的类型
class Hash = hash, //确定元素存储位置所用的哈希函数
class Pred = equal_to, //判断各个元素是否相等所用的函数
class Alloc = allocator //指定分配器对象的类型
> class unordered_set;
在这些参数中,只有第一个参数是没有默认值。
即在创建 int 、char 等内置类型的 unordered_set 时只需传入存储在容器中的类型即可。
但是,对于没有默认的哈希函数的类型,如自定义的 class 类型,pair 类型等,
就必须自己指定一个哈希函数。
这也是为什么直接构建 pair 类型的 unordered_set 如 unordered_set<pair<int, int>> uset
会出现问题(不会在声明时报错,而是在 insert 等操作时)。
对于这种情况,只需要将上面的第二个参数:
确定元素存储位置所用的哈希函数,也在声明时传入就行。
关于哈希函数的选择,不同的情景会有所不同。
这里笔者给出一个最简单的针对 pair 类型的哈希函数。
struct SimplePairHash {
std::size_t operator()(const std::pair<int, int>& p) const {
return p.first ^ p.second;
}
};
类似题目-岛屿数量
class Solution {
public:
vector<vector<bool>> visited;
int row, col;
int isLandNum;
vector<vector<int>> dir = {{-1, 1, 0, 0}, {0, 0, -1, 1}};
void dfs(vector<vector<char>>& grid, int i, int j) {
visited[i][j] = true;
for (int d = 0; d < dir[0].size(); d++) {
int new_i = i + dir[0][d];
int new_j = j + dir[1][d];
if (new_i >= 0 && new_i < row && new_j >= 0 && new_j < col &&
grid[new_i][new_j] != '0' && visited[new_i][new_j] == false) {
dfs(grid, new_i, new_j);
}
}
}
int numIslands(vector<vector<char>>& grid) {
row = grid.size();
col = grid[0].size();
visited.resize(row);
for(int i = 0; i < row; i++) {
visited[i].resize(col, false);
}
isLandNum = 0;
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
if (grid[i][j] != '0' && visited[i][j] == false) {
dfs(grid, i, j);
isLandNum++;
}
}
}
return isLandNum;
}
};