1. 200. 岛屿数量

这道题是经典的二维网格连通域问题,核心思路是深度优先搜索(DFS) 或广度优先搜索(BFS),遍历网格找到所有独立的陆地连通块(岛屿)。
解题原理
- 遍历网格:逐个检查每个格子,如果当前格子是陆地('1'),说明找到一座新岛屿,岛屿数量 + 1。
- 淹没连通陆地:找到陆地后,
用 DFS/BFS 把所有相邻(上下左右)的连通陆地全部标记为水('0'),避免重复计数。 - 统计结果:遍历完成后,统计的岛屿数量就是答案。
py
#include <vector>
using namespace std;
class Solution {
public:
int numIslands(vector<vector<char>>& grid) {
// 空网格直接返回0
if (grid.empty() || grid[0].empty()) return 0;
int row = grid.size(); // 网格行数
int col = grid[0].size(); // 网格列数
int count = 0; // 岛屿数量
// 遍历每一个格子
for (int i = 0; i < row; ++i) {
for (int j = 0; j < col; ++j) {
// 找到陆地,岛屿数+1
if (grid[i][j] == '1') {
count++;
// DFS淹没当前岛屿所有连通陆地
dfs(grid, i, j, row, col);
}
}
}
return count;
}
private:
// DFS递归函数:淹没(i,j)位置及相邻的陆地
void dfs(vector<vector<char>>& grid, int i, int j, int row, int col) {
// 边界判断:超出网格范围 或 当前是水,直接返回
if (i < 0 || i >= row || j < 0 || j >= col || grid[i][j] == '0') {
return;
}
// 把当前陆地淹没为水
grid[i][j] = '0';
// 递归遍历上下左右四个方向
dfs(grid, i - 1, j, row, col); // 上
dfs(grid, i + 1, j, row, col); // 下
dfs(grid, i, j - 1, row, col); // 左
dfs(grid, i, j + 1, row, col); // 右
}
};
2. 1020. 飞地的数量
给你一个大小为 m x n 的二进制矩阵 grid ,其中 0 表示一个海洋单元格、1 表示一个陆地单元格。
一次 移动 是指从一个陆地单元格走到另一个相邻(上、下、左、右)的陆地单元格或跨过 grid 的边界。
返回网格中 无法 在任意次数的移动中离开网格边界的陆地单元格的数量。

这道题和岛屿数量思路几乎一样,核心是:
先把能接触边界的陆地全部淹没,剩下的陆地就是飞地。
解题原理
1.飞地定义:无法到达网格边界的陆地。
2.反向思维:
-
先遍历四条边界上的所有陆地,
把它们连通的所有陆地全部淹没(这些都不是飞地)。 -
最后统计网格中
剩下的陆地数量,就是答案。 -
依然用 DFS 实现,逻辑简单易懂。
py
#include <vector>
using namespace std;
class Solution {
public:
int numEnclaves(vector<vector<int>>& grid) {
if (grid.empty() || grid[0].empty()) return 0;
int m = grid.size(); // 行数
int n = grid[0].size(); // 列数
// 1. 淹没【四条边界】上所有能连通的陆地
// 左右两列(j=0 和 j=n-1)
for (int i = 0; i < m; ++i) {
if (grid[i][0] == 1) {
dfs(grid, i, 0, m, n);
}
if (grid[i][n-1] == 1) {
dfs(grid, i, n-1, m, n);
}
}
// 上下两行(i=0 和 i=m-1)
for (int j = 0; j < n; ++j) {
if (grid[0][j] == 1) {
dfs(grid, 0, j, m, n);
}
if (grid[m-1][j] == 1) {
dfs(grid, m-1, j, m, n);
}
}
// 2. 统计剩下的陆地 = 飞地数量
int count = 0;
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
if (grid[i][j] == 1) {
count++;
}
}
}
return count;
}
private:
// DFS:淹没陆地
void dfs(vector<vector<int>>& grid, int i, int j, int m, int n) {
// 越界 / 不是陆地,直接返回
if (i < 0 || i >= m || j < 0 || j >= n || grid[i][j] == 0) {
return;
}
// 淹没当前陆地
grid[i][j] = 0;
// 上下左右
dfs(grid, i-1, j, m, n);
dfs(grid, i+1, j, m, n);
dfs(grid, i, j-1, m, n);
dfs(grid, i, j+1, m, n);
}
};
3. 695. 岛屿的最大面积
- 给你一个大小为
m x n的二进制矩阵 grid 。- 岛屿 是由一些相邻的
1(代表土地) 构成的组合,这里的「相邻」要求两个 1 必须在水平或者竖直的四个方向上 相邻。你可以假设 grid 的四个边缘都被0(代表水)包围着。- 岛屿的面积是岛上值为 1 的单元格的数目。计算并返回 grid 中最大的岛屿面积。如果没有岛屿,则返回面积为 0

这道题是岛屿数量的经典变种,核心思路:
遍历每个岛屿,计算每座岛屿的面积,记录最大值。
解题原理
- 遍历网格:逐个检查每个格子,
遇到陆地(1)就开始计算这座岛屿的面积。 - DFS 计算面积:
用 DFS 淹没连通陆地,并统计当前岛屿的单元格数量(面积)。 - 记录最大值:
每次算出一座岛屿的面积,就和全局最大值比较,更新最大面积。 - 最终返回:遍历完所有岛屿,返回最大面积。
py
#include <vector>
#include <algorithm> // 用于 max 函数
using namespace std;
class Solution {
public:
int maxAreaOfIsland(vector<vector<int>>& grid) {
if (grid.empty() || grid[0].empty()) return 0;
int m = grid.size(); // 行数
int n = grid[0].size(); // 列数
int maxArea = 0; // 记录最大岛屿面积
// 遍历所有格子
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
// 找到陆地,计算当前岛屿面积
if (grid[i][j] == 1) {
int currentArea = dfs(grid, i, j, m, n);
maxArea = max(maxArea, currentArea); // 更新最大值
}
}
}
return maxArea;
}
private:
// DFS:返回当前岛屿的面积
int dfs(vector<vector<int>>& grid, int i, int j, int m, int n) {
// 越界 / 是水,返回 0
if (i < 0 || i >= m || j < 0 || j >= n || grid[i][j] == 0) {
return 0;
}
// 淹没当前陆地(避免重复计算)
grid[i][j] = 0;
// 面积 = 当前1 + 上下左右的面积
return 1
+ dfs(grid, i-1, j, m, n) // 上
+ dfs(grid, i+1, j, m, n) // 下
+ dfs(grid, i, j-1, m, n) // 左
+ dfs(grid, i, j+1, m, n); // 右
}
};
4. 827. 最大人工岛

这道题是岛屿的最大面积进阶版,难度大,但思路非常清晰:先给每个岛屿编号 + 记录面积 → 遍历每个 0,看它四周能连接哪些不同岛屿 → 计算连接后的总面积 → 取最大值。
解题核心原理
-
- 给岛屿编号:遍历所有陆地,用 DFS 给每座独立岛屿标上唯一编号(2,3,4...),同时用哈希表记录每个编号对应的岛屿面积。
-
- 尝试填海造陆:遍历每个海洋(0),查看它上下左右四个方向的相邻岛屿。
- 收集不同编号的岛屿面积(避免重复加同一个岛)。
- 把这些面积 + 1(填的这一格)就是造陆后的总面积。
-
3.取最大值:对比所有可能的造陆结果,返回最大面积。
- 如果全是陆地,直接返回网格总面积。
py
#include <vector>
#include <unordered_set>
#include <unordered_map>
#include <algorithm>
using namespace std;
class Solution {
public:
int largestIsland(vector<vector<int>>& grid) {
int n = grid.size();
// key:岛屿编号,value:岛屿面积
unordered_map<int, int> area;
int num = 2; // 岛屿编号从2开始(0海洋,1陆地)
int max_area = 0;
// 第一步:DFS给所有岛屿编号,记录面积
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
if (grid[i][j] == 1) {
area[num] = dfs(grid, i, j, num, n);
max_area = max(max_area, area[num]); // 记录原始最大岛
num++;
}
}
}
// 第二步:遍历所有0,尝试填海造陆
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
if (grid[i][j] == 0) {
unordered_set<int> visited; // 记录已访问的岛屿编号,防重复
int cur = 1; // 填当前这格0,面积+1
// 检查上下左右四个方向
for (auto& d : dirs) {
int x = i + d.first;
int y = j + d.second;
if (x >= 0 && x < n && y >= 0 && y < n) {
int id = grid[x][y];
if (id > 1 && !visited.count(id)) { // 是岛屿且没加过
visited.insert(id);
cur += area[id];
}
}
}
max_area = max(max_area, cur);
}
}
}
return max_area;
}
private:
// 上下左右方向数组
vector<pair<int, int>> dirs = {{-1,0}, {1,0}, {0,-1}, {0,1}};
// DFS:给岛屿编号,返回岛屿面积
int dfs(vector<vector<int>>& grid, int i, int j, int num, int n) {
// 越界 / 不是未编号的陆地,返回0
if (i < 0 || i >= n || j < 0 || j >= n || grid[i][j] != 1) {
return 0;
}
grid[i][j] = num; // 编号
int area = 1;
// 累加四个方向
for (auto& d : dirs) {
area += dfs(grid, i + d.first, j + d.second, num, n);
}
return area;
}
};