Chapter 17 Graphs (1)
基本题目
797. 所有可能的路径
当前路径记录+回溯+DFS 递归
class Solution {
public:
void dfs(vector<vector<int>>& result, vector<bool> &inPath, vector<int> &path, vector<vector<int>>& graph) {
int pos = path.back();
if (pos == graph.size() - 1) {
result.push_back(path);
return;
}
for (const int &v : graph[pos]) {
if (!inPath[v]) {
path.push_back(v);
inPath[v] = true;
dfs(result, inPath, path, graph);
inPath[v] = false;
path.pop_back();
}
}
}
vector<vector<int>> allPathsSourceTarget(vector<vector<int>>& graph) {
vector<bool> inPath(graph.size(), false);
vector<int> path;
vector<vector<int>> result;
path.push_back(0);
inPath[0] = true;
dfs(result, inPath, path, graph);
return result;
}
};
确保不存在环时,可以省略 inPath,不记录节点是否访问过
200. 岛屿数量
DFS 搜索
class Solution {
public:
void search(vector<vector<char>>& grid, vector<vector<bool>>& searched, int i, int j) {
if (searched[i][j]) return;
searched[i][j] = true;
if (grid[i][j] == '0') return;
int m = grid.size(), n = grid[0].size();
if (i > 0) search(grid, searched, i - 1, j);
if (j < n - 1) search(grid, searched, i, j + 1);
if (i < m - 1) search(grid, searched, i + 1, j);
if (j > 0) search(grid, searched, i, j - 1);
}
int numIslands(vector<vector<char>>& grid) {
int m = grid.size(), n = grid[0].size();
vector<vector<bool>> searched(m, vector<bool>(n, false));
int count = 0;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (!searched[i][j]) {
if (grid[i][j] == '1') count++;
search(grid, searched, i, j);
}
}
}
return count;
}
};
BFS 搜索
class Solution {
public:
int numIslands(vector<vector<char>>& grid) {
int m = grid.size(), n = grid[0].size();
vector<vector<bool>> searched(m, vector<bool>(n, false));
int count = 0;
queue<pair<int, int>> q;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (!searched[i][j]) {
searched[i][j] = true;
if (grid[i][j] == '1') {
count++;
q.push({i, j});
while (!q.empty()) {
pair<int, int> pos = q.front();
q.pop();
int r = pos.first, c = pos.second;
if (grid[r][c] == '1') {
if (r > 0 && !searched[r - 1][c]) {
q.push({r - 1, c});
searched[r - 1][c] = true;
}
if (c < n - 1 && !searched[r][c + 1]) {
q.push({r, c + 1});
searched[r][c + 1] = true;
}
if (r < m - 1 && !searched[r + 1][c]) {
q.push({r + 1, c});
searched[r + 1][c] = true;
}
if (c > 0 && !searched[r][c - 1]) {
q.push({r, c - 1});
searched[r][c - 1] = true;
}
}
}
}
}
}
}
return count;
}
};
本题还可以转化为并查集问题,会在后续题目中探讨
695. 岛屿的最大面积
与 200. 岛屿数量 基本一致,在搜索过程中维护岛屿面积
可以采用递归 DFS、迭代 DFS、迭代 BFS
class Solution {
public:
int maxAreaOfIsland(vector<vector<int>>& grid) {
int m = grid.size(), n = grid[0].size();
vector<vector<bool>> searched(m, vector<bool>(n, false));
int maxArea = 0;
queue<pair<int, int>> q;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (!searched[i][j]) {
searched[i][j] = true;
if (grid[i][j]) {
int area = 0;
q.push({i, j});
while (!q.empty()) {
pair<int, int> pos = q.front();
q.pop();
int r = pos.first, c = pos.second;
if (grid[r][c]) {
area++;
if (r > 0 && !searched[r - 1][c]) {
q.push({r - 1, c});
searched[r - 1][c] = true;
}
if (c < n - 1 && !searched[r][c + 1]) {
q.push({r, c + 1});
searched[r][c + 1] = true;
}
if (r < m - 1 && !searched[r + 1][c]) {
q.push({r + 1, c});
searched[r + 1][c] = true;
}
if (c > 0 && !searched[r][c - 1]) {
q.push({r, c - 1});
searched[r][c - 1] = true;
}
}
}
maxArea = max(maxArea, area);
}
}
}
}
return maxArea;
}
};
1020. 飞地的数量
同前几题,在 DFS/BFS 的过程中判断该区域是否有效,仅当有效时再加到结果中
class Solution {
public:
int numEnclaves(vector<vector<int>>& grid) {
int m = grid.size(), n = grid[0].size();
int total = 0;
queue<pair<int, int>> q;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (grid[i][j]) {
grid[i][j] = 0;
int area = 0, valid = 1;
q.push({i, j});
while (!q.empty()) {
area++;
pair<int, int> pos = q.front();
q.pop();
int r = pos.first, c = pos.second;
if (r == 0 || r == m - 1 || c == 0 || c == n - 1) {
valid = 0;
}
if (r > 0 && grid[r - 1][c]) {
q.push({r - 1, c});
grid[r - 1][c] = 0;
}
if (c < n - 1 && grid[r][c + 1]) {
q.push({r, c + 1});
grid[r][c + 1] = 0;
}
if (r < m - 1 && grid[r + 1][c]) {
q.push({r + 1, c});
grid[r + 1][c] = 0;
}
if (c > 0 && grid[r][c - 1]) {
q.push({r, c - 1});
grid[r][c - 1] = 0;
}
}
total += area * valid;
}
}
}
return total;
}
};
130. 被围绕的区域
同前几题,在 DFS/BFS 的过程中判断该区域是否有效,有效时标记该区域所有位置
class Solution {
public:
void solve(vector<vector<char>>& board) {
int m = board.size(), n = board[0].size();
vector<vector<bool>> searched(m, vector<bool>(n, false));
queue<pair<int, int>> q;
vector<pair<int, int>> region;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (!searched[i][j] && board[i][j] == 'O') {
int area = 0, valid = 1;
q.push({i, j});
searched[i][j] = true;
while (!q.empty()) {
pair<int, int> pos = q.front();
q.pop();
int r = pos.first, c = pos.second;
if (board[r][c] == 'O') {
region.push_back(pos);
if (r == 0 || r == m - 1 || c == 0 || c == n - 1) {
valid = 0;
}
if (r > 0 && !searched[r - 1][c]) {
q.push({r - 1, c});
searched[r - 1][c] = true;
}
if (c < n - 1 && !searched[r][c + 1]) {
q.push({r, c + 1});
searched[r][c + 1] = true;
}
if (r < m - 1 && !searched[r + 1][c]) {
q.push({r + 1, c});
searched[r + 1][c] = true;
}
if (c > 0 && !searched[r][c - 1]) {
q.push({r, c - 1});
searched[r][c - 1] = true;
}
}
}
if (valid) {
for (const pair<int, int> &pos : region) {
board[pos.first][pos.second] = 'X';
}
}
region.clear();
}
}
}
}
};
可以从判断有效的规则出发:先考虑边界的方格,将那些区域标记即可
class Solution {
public:
void dfs(vector<vector<char>>& result, vector<vector<char>>& board, int i, int j) {
int m = board.size(), n = board[0].size();
if (i < 0 || i >= m || j < 0 || j >= n) return;
if (result[i][j] == 'O' || board[i][j] == 'X') return;
result[i][j] = 'O';
dfs(result, board, i - 1, j);
dfs(result, board, i + 1, j);
dfs(result, board, i, j - 1);
dfs(result, board, i, j + 1);
}
void solve(vector<vector<char>>& board) {
int m = board.size(), n = board[0].size();
vector<vector<char>> result(m, vector<char>(n, 'X'));
for (int i = 0; i < m; i++) {
dfs(result, board, i, 0);
dfs(result, board, i, n - 1);
}
for (int j = 0; j < n; j++) {
dfs(result, board, 0, j);
dfs(result, board, m - 1, j);
}
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
board[i][j] = result[i][j];
}
}
}
};
417. 太平洋大西洋水流问题
起点不明确但终点明确:从终点出发搜索
class Solution {
public:
void dfs(vector<vector<int>>& heights, vector<vector<bool>>& reachable, int i, int j) {
if (reachable[i][j]) return;
reachable[i][j] = true;
int m = heights.size(), n = heights[0].size();
if (i > 0 && heights[i - 1][j] >= heights[i][j]) dfs(heights, reachable, i - 1, j);
if (i < m - 1 && heights[i + 1][j] >= heights[i][j]) dfs(heights, reachable, i + 1, j);
if (j > 0 && heights[i][j - 1] >= heights[i][j]) dfs(heights, reachable, i, j - 1);
if (j < n - 1 && heights[i][j + 1] >= heights[i][j]) dfs(heights, reachable, i, j + 1);
}
vector<vector<int>> pacificAtlantic(vector<vector<int>>& heights) {
int m = heights.size(), n = heights[0].size();
vector<vector<bool>> pacific(m, vector<bool>(n, false));
vector<vector<bool>> atlantic(m, vector<bool>(n, false));
for (int i = 0; i < m; i++) dfs(heights, pacific, i, 0);
for (int j = 0; j < n; j++) dfs(heights, pacific, 0, j);
for (int i = 0; i < m; i++) dfs(heights, atlantic, i, n - 1);
for (int j = 0; j < n; j++) dfs(heights, atlantic, m - 1, j);
vector<vector<int>> result;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (pacific[i][j] && atlantic[i][j]) {
result.push_back({i, j});
}
}
}
return result;
}
};
827. 最大人工岛
先计算每个格子所属的岛屿及面积,后遍历空格计算最大值
class Solution {
public:
int largestIsland(vector<vector<int>>& grid) {
int m = grid.size(), n = grid[0].size();
vector<vector<int>> islandIdx(m, vector<int>(n, -1));
vector<int> islandSizes;
queue<pair<int, int>> q;
int id = 0;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (grid[i][j] && islandIdx[i][j] < 0) {
int size = 0;
q.push({i, j});
islandIdx[i][j] = id;
while (!q.empty()) {
pair<int, int> pos = q.front();
q.pop();
int r = pos.first, c = pos.second;
if (!grid[r][c]) continue;
size++;
if (r > 0 && grid[r - 1][c] && islandIdx[r - 1][c] < 0) {
q.push({r - 1, c});
islandIdx[r - 1][c] = id;
}
if (c < n - 1 && grid[r][c + 1] && islandIdx[r][c + 1] < 0) {
q.push({r, c + 1});
islandIdx[r][c + 1] = id;
}
if (r < m - 1 && grid[r + 1][c] && islandIdx[r + 1][c] < 0) {
q.push({r + 1, c});
islandIdx[r + 1][c] = id;
}
if (c > 0 && grid[r][c - 1] && islandIdx[r][c - 1] < 0) {
q.push({r, c - 1});
islandIdx[r][c - 1] = id;
}
}
islandSizes.push_back(size);
id++;
}
}
}
int maxSize = 0;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (islandIdx[i][j] < 0) {
int size = 1;
unordered_set<int> s;
if (i > 0 && islandIdx[i - 1][j] >= 0 && !s.count(islandIdx[i - 1][j])) {
s.insert(islandIdx[i - 1][j]);
size += islandSizes[islandIdx[i - 1][j]];
}
if (j > 0 && islandIdx[i][j - 1] >= 0 && !s.count(islandIdx[i][j - 1])) {
s.insert(islandIdx[i][j - 1]);
size += islandSizes[islandIdx[i][j - 1]];
}
if (i < m - 1 && islandIdx[i + 1][j] >= 0 && !s.count(islandIdx[i + 1][j])) {
s.insert(islandIdx[i + 1][j]);
size += islandSizes[islandIdx[i + 1][j]];
}
if (j < n - 1 && islandIdx[i][j + 1] >= 0 && !s.count(islandIdx[i][j + 1])) {
s.insert(islandIdx[i][j + 1]);
size += islandSizes[islandIdx[i][j + 1]];
}
maxSize = max(maxSize, size);
}
}
}
if (maxSize == 0) return islandSizes[0];
return maxSize;
}
};