leetcode:1020. 飞地的数量

题目

给你一个大小为 m x n 的二进制矩阵 grid ,其中 0 表示一个海洋单元格、1 表示一个陆地单元格。
一次 移动 是指从一个陆地单元格走到另一个相邻(上、下、左、右)的陆地单元格或跨过 grid 的边界。
返回网格中 无法 在任意次数的移动中离开网格边界的陆地单元格的数量。

示例 1:
[中等] 1020. 飞地的数量 - 图1

  1. 输入:grid = [[0,0,0,0],[1,0,1,0],[0,1,1,0],[0,0,0,0]]
  2. 输出:3
  3. 解释:有三个 1 0 包围。一个 1 没有被包围,因为它在边界上。
  4. 来源:力扣(LeetCode
  5. 链接:https://leetcode-cn.com/problems/number-of-enclaves
  6. 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

示例 2:
[中等] 1020. 飞地的数量 - 图2

输入:grid = [[0,1,1,0],[0,0,1,0],[0,0,1,0],[0,0,0,0]]
输出:0
解释:所有 1 都在边界上或可以到达边界。

解答 & 代码

[中等] 1254. 统计封闭岛屿的数目
本题思路和上题基本相同
只有靠边界的岛屿(即存在某个格子在边界上的岛屿)才是可到达的,剩余的岛屿格子都是不可到底的飞地。
因此,只需要先将靠边界的岛屿淹掉(都变为 0),在统计剩余的陆地单元格(1)的个数,就是飞地数量

class Solution {
private:
    // 深度优先搜索,将当前岛屿淹没。即从位置 (row, col) 开始,将与之相邻的都置 0(即变为海水)
    void dfs(vector<vector<int>>& grid, int row, int col)
    {
        int rows = grid.size();
        int cols = grid[0].size();
        // 递归结束条件:越界 or 已经是海水
        if(row < 0 || row >= rows || col < 0 || col >= cols || grid[row][col] == 0)
            return;
        // 将 (row, col) 位置置 0(即变为海水)
        grid[row][col] = 0;
        // 递归搜索上、下、左、右,将当前岛屿的每个位置都变为 1(即变为海水)
        dfs(grid, row - 1, col);
        dfs(grid, row + 1, col);
        dfs(grid, row, col - 1);
        dfs(grid, row, col + 1);
    }
public:
    int numEnclaves(vector<vector<int>>& grid) {
        if(grid.size() == 0 || grid[0].size() == 0)
            return 0;
        int rows = grid.size();
        int cols = grid[0].size();

        // 去掉靠上、下、左、右边界的岛屿(置为 0,相当于淹掉)
        for(int col = 0; col < cols; ++col)
        {
            dfs(grid, 0, col);            // 靠上边界的岛屿淹掉(变为海水 0)
            dfs(grid, rows - 1, col);    // 靠下边界的岛屿淹掉(变为海水 0)
        }
        for(int row = 0; row < rows; ++row)
        {
            dfs(grid, row, 0);            // 靠左边界的岛屿淹掉(变为海水 0)
            dfs(grid, row, cols - 1);    // 靠右边界的岛屿淹掉(变为海水 0)
        }

        // 剩下的陆地单元格(为 1 的格子)都是无法到达的飞地
        // 因此统计剩下的值为 1 的格子的个数即可
        int cnt = 0;
        for(int row = 0; row < rows; ++row)
        {
            for(int col = 0; col < cols; ++col)
            {
                if(grid[row][col] == 1)
                    ++cnt;
            }
        }
        return cnt;
    }
};

复杂度分析:设矩阵 M 行 N 列

  • 时间复杂度 O(MN)
  • 空间复杂度 O(MN):在最坏情况下,整个网格均为陆地,深度优先搜索的深度达到 MN,即空间复杂度达到 O(MN)

执行结果:

执行结果:通过

执行用时:36 ms, 在所有 C++ 提交中击败了 99.66% 的用户
内存消耗:21.1 MB, 在所有 C++ 提交中击败了 86.83% 的用户