洪水填充是在图中常用的技巧,在遍历图的过程中,修改路径信息来剪枝,类似染色,使得每一
片区域可以得到区分。其时间复杂度和图的规模是相同的
class Solution {
public:
void f(vector<vector<char>>& grid, int i, int j) {
if (i < 0 || i >= grid.size() || j < 0 || j >= grid[0].size() ||
grid[i][j] != '1')
return;
grid[i][j] = 0;
f(grid, i - 1, j);
f(grid, i + 1, j);
f(grid, i, j + 1);
f(grid, i, j - 1);
}
int numIslands(vector<vector<char>>& grid) {
int ans = 0;
for (int i = 0; i < grid.size(); i++) {
for (int j = 0; j < grid[0].size(); j++) {
if (grid[i][j] == '1') {
ans++;
f(grid, i, j);
}
}
}
return ans;
}
};
此题是一个模板题,设置f函数进行dfs,将一片区域的点全部染色并加以区分
public class Solution{
public static void solve(char[][] board) {
int n = board.length;
int m = board[0].length;
for (int j = 0; j < m; j++) {
if (board[0][j] == 'O') {
dfs(board, n, m, 0, j);
}
if (board[n - 1][j] == 'O') {
dfs(board, n, m, n - 1, j);
}
}
for (int i = 1; i < n - 1; i++) {
if (board[i][0] == 'O') {
dfs(board, n, m, i, 0);
}
if (board[i][m - 1] == 'O') {
dfs(board, n, m, i, m - 1);
}
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (board[i][j] == 'O') {
board[i][j] = 'X';
}
if (board[i][j] == 'F') {
board[i][j] = 'O';
}
}
}
}
public static void dfs(char[][] board, int n, int m, int i, int j) {
if (i < 0 || i == n || j < 0 || j == m || board[i][j] != 'O') {
return;
}
board[i][j] = 'F';
dfs(board, n, m, i + 1, j);
dfs(board, n, m, i - 1, j);
dfs(board, n, m, i, j + 1);
dfs(board, n, m, i, j - 1);
}
}
此题就是将不与边界相连的区域修改。要去找不与边界相连的区域较难,可以先将与边界相连的区域染色,剩下的就是边界内的,遍历进行修改
class Solution {
public:
int sign = 2;
int count = 0;
void f(vector<vector<int>>& grid, int i, int j) {
if (i < 0 || i >= grid.size() || j < 0 || j >= grid[0].size() ||
grid[i][j] != 1)
return;
grid[i][j] = sign;
count++;
f(grid, i, j - 1);
f(grid, i, j + 1);
f(grid, i - 1, j);
f(grid, i + 1, j);
}
int ans = 0;
int largestIsland(vector<vector<int>>& grid) {
unordered_map<int, int> rem;
for (int i = 0; i < grid.size(); i++) {
for (int j = 0; j < grid[0].size(); j++) {
if (grid[i][j] == 1) {
f(grid, i, j);
rem[sign] = count;
sign++;
ans = max(ans, count);
count = 0;
}
}
}
unordered_set<int> visit;
for (int i = 0; i < grid.size(); i++) {
for (int j = 0; j < grid[0].size(); j++) {
if (grid[i][j] == 0) {
int cur = 0;
if (i > 0 && grid[i - 1][j] != 0 &&
visit.find(grid[i - 1][j]) == visit.end()) {
visit.insert(grid[i - 1][j]);
cur += rem[grid[i - 1][j]];
}
if (i < grid.size() - 1 && grid[i + 1][j] != 0 &&
visit.find(grid[i + 1][j]) == visit.end()) {
visit.insert(grid[i + 1][j]);
cur += rem[grid[i + 1][j]];
}
if (j > 0 && grid[i][j - 1] != 0 &&
visit.find(grid[i][j - 1]) == visit.end()) {
visit.insert(grid[i][j - 1]);
cur += rem[grid[i][j - 1]];
}
if (j < grid[0].size() - 1 && grid[i][j + 1] != 0 &&
visit.find(grid[i][j + 1]) == visit.end()) {
visit.insert(grid[i][j + 1]);
cur += rem[grid[i][j + 1]];
}
ans = max(ans, cur + 1);
visit.clear();
}
}
}
return ans;
}
};
填充一个格,求填充之后最大的连通面积。可以先将不同的区域进行统计并染色,然后遍历数组依次尝试并找出最大值
class Solution {
public:
int dfs(vector<vector<int>>& grid, int i, int j) {
if (i < 0 || i >= grid.size() || j < 0 || j >= grid[0].size() ||
grid[i][j] != 1)
return 0;
grid[i][j] = 2;
return 1 + dfs(grid, i + 1, j) + dfs(grid, i - 1, j) +
dfs(grid, i, j + 1) + dfs(grid, i, j - 1);
}
bool judge(vector<vector<int>>& grid, int x, int y) {
if (grid[x][y] == 1 &&
(x == 0 || (x > 0 && grid[x - 1][y] == 2) ||
(x < grid.size() - 1 && grid[x + 1][y] == 2) ||
(y > 0 && grid[x][y - 1] == 2) ||
(y < grid[0].size() - 1 && grid[x][y + 1] == 2)))
return true;
return false;
}
vector<int> hitBricks(vector<vector<int>>& grid,
vector<vector<int>>& hits) {
int n = grid.size(), m = grid[0].size();
vector<int> ans(hits.size(), 0);
if (n == 1)
return ans;
for (auto i : hits) {
grid[i[0]][i[1]]--;
}
for (int i = 0; i < m; i++)
dfs(grid, 0, i);
for (int i = hits.size() - 1; i >= 0; i--) {
int x = hits[i][0];
int y = hits[i][1];
grid[x][y]++;
if (judge(grid, x, y)) {
int cur = dfs(grid, x, y) - 1;
ans[i] = cur;
}
}
return ans;
}
};
打砖块的时间是有时间循序的,对于一个时间点打掉的砖块,跟之前打掉的砖块和与之相连的砖块是有关的,正向思考是不容易做的,可以逆向思考,先将要打掉的砖块标记,然后从最晚时间打掉的砖块开始向前填充他能打掉的砖块并记录(只有这个砖块的相邻砖块有不掉落的或者他本是就是在天花板上的砖块才可以),只要在符合条件那么他周围可以掉的砖块都是他要打掉的因为既然这些砖块与最晚打掉的砖块相连,即使他们和较早时间打掉的砖块相连,那也不会让较早时间打掉的砖块打掉。这种技巧叫做"时间倒流"技巧,在涉及先后顺序的题中是常用的技巧