Leetcode 1254. 统计封闭岛屿的数目
题目:
有一个二维矩阵 grid ,每个位置要么是陆地(记号为 0 )要么是水域(记号为 1 )。
我们从一块陆地出发,每次可以往上下左右 4 个方向相邻区域走,能走到的所有陆地区域,我们将其称为一座「岛屿」。
如果一座岛屿 完全 由水域包围,即陆地边缘上下左右所有相邻区域都是水域,那么我们将其称为 「封闭岛屿」。
请返回封闭岛屿的数目。
输入:grid = [[1,1,1,1,1,1,1,0],[1,0,0,0,0,1,1,0],[1,0,1,0,1,1,1,0],[1,0,0,0,0,1,0,1],[1,1,1,1,1,1,1,0]]
输出:2
解释:灰色区域的岛屿是封闭岛屿,因为这座岛屿完全被水域包围(即被 1 区域包围)。
分析:
1.对于边界而言,即使其为陆地,也至少存在一个变不能临近水域,所以不可能构成孤岛;
2.对于边界上的陆地而言,其相邻的陆地,肯定也构不成孤岛,即所能到达的陆地,均不可以。
3.对于剩余区域的陆地X,其所能到达的陆地Y,能够和X构成同一片岛屿。
方案:(参考别人的https://leetcode-cn.com/problems/number-of-closed-islands/solution/yi-ti-kan-tou-dfs-he-dfs-by-xiao-xiao-suan-fa/)
直接从边界的陆地开始DFS或BFS遍历,只要边界陆地能遍历到的地方就不是封闭岛屿,同时我们也要将遍历过得点置为1,表示该位置已经遍历过。最后,里面为0的位置都是属于封闭岛屿的陆地了。
代码部分:
1 #include <iostream> 2 #include <vector> 3 using namespace std; 4 5 void dfs(int x, int y, vector<vector<int>>& grid) { 6 int xlen = grid.size(); //行 7 int ylen = grid[0].size(); //列 8 if (x >= xlen || y >= ylen || x < 0 || y < 0 || grid[x][y] == 1) { //越界或者为水域,直接返回 9 return; 10 } 11 grid[x][y] = 1; //标记已遍历过的节点 12 int vx[] = { 0, 1, 0, -1 }; //记录四个方向,如vx[0],vy[0],即横坐标不变,纵坐标加1,向上移动一步 13 int vy[] = { 1, 0, -1, 0 }; 14 for (int i = 0; i < 4; i++) 15 { 16 dfs(x + vx[i],y + vy[i],grid); //遍历剩余四个方向 17 } 18 } 19 20 void printGrid(vector<vector<int> > grid) { //打印二维矩阵 21 for (int i = 0; i < grid.size(); i++) 22 { 23 for (int j = 0; j < grid[0].size(); j++) 24 { 25 cout << grid[i][j] << " "; 26 } 27 cout << endl; 28 } 29 } 30 31 int closedIsland(vector<vector<int> > &grid) 32 { 33 int result = 0; 34 int y = grid.size(); //一共有多少行 35 int x = grid[0].size(); 36 int i, j; 37 //从边界往里遍历,凡是能到达的所有陆地,均不能构成闭合岛屿 38 for (i = 0; i < y; i++) { 39 for (j= 0; j < x; j++) 40 { 41 if (i == 0 || j == 0 || i == y - 1 || j == x - 1) { 42 dfs(i, j, grid); 43 } 44 } 45 } 46 cout << "\n边界处理完成后的结果:" << endl; 47 printGrid(grid); 48 //继续遍历,剩余结点中,某个陆地x能到达的所有区域,构成一个孤岛,统计有多少个这样的x 49 for (i = 0; i < grid.size(); i++) 50 { 51 for (j= 0; j < grid[0].size(); j++) 52 { 53 if (grid[i][j] == 0) //起点,遍历结束后,所有可到达的点被标记为水域,即产生一个孤岛 54 { 55 result++; 56 dfs(i,j,grid); 57 } 58 } 59 } 60 return result; 61 } 62 63 64 int main() { 65 vector<vector<int> > grid; 66 //输入二维矩阵 67 int m, n; 68 cin >> m >> n; 69 vector<int> temp(n); //结束临时一维数组构建二维数组 70 grid.resize(m,temp); //二维数组大小初始化(注意用法) 71 int i, j; 72 for (i = 0; i < m; i++) 73 { 74 for (j = 0; j < n;j++) 75 { 76 cin >> grid[i][j]; //输入二维数组元素 77 } 78 } 79 80 cout << "\n孤岛计算结果:" << closedIsland(grid) << endl; //输出计算结果 81 82 83 }
运行结果:
分析:
第一步是将1,2两块区域排除,毕竟它们处于边界,不可能成为孤岛区域
第二步是找出3,4,两块区域,比如第4块,想从左上角开始深度优先遍历(当然广度也可以),岂能到达的所有陆地领域都是联通的,共同构成一个孤岛,因此,ret+1;
最后,返回结果!