zoukankan      html  css  js  c++  java
  • 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 << "
    边界处理完成后的结果:" << 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 << "
    孤岛计算结果:" << closedIsland(grid) << endl;  //输出计算结果
    81 
    82 
    83 }

    运行结果:

      

     分析:

      

      第一步是将1,2两块区域排除,毕竟它们处于边界,不可能成为孤岛区域

      第二步是找出3,4,两块区域,比如第4块,想从左上角开始深度优先遍历(当然广度也可以),岂能到达的所有陆地领域都是联通的,共同构成一个孤岛,因此,ret+1;

      最后,返回结果!

  • 相关阅读:
    chrome调试Android webview页面
    Ractive 的 一些认识
    backbone的一些认识
    关于Maven打包(Jar)时文件过滤的正确做法
    网页中实现微信登录(OAuth)的不完整记录
    将项目发布到Maven中央仓库时关于GPG的一些操作日志
    记录一下自己在 eclipse 中使用的 javadoc 模板
    记录一下MySQL的表分区常用操作
    在H5 App中实现自定义Token的注意事项
    再来复习一下Javascript中关于数组和对象的常用方法
  • 原文地址:https://www.cnblogs.com/cnyulei/p/11898013.html
Copyright © 2011-2022 走看看