(图论) 1020. 飞地的数量 ——【Leetcode每日一题】

❓ 1020. 飞地的数量

难度:中等

给你一个大小为 m x n 的二进制矩阵 grid ,其中 0 表示一个 海洋单元格 、1 表示一个 陆地单元格。

一次 移动 是指从一个陆地单元格 走到另一个相邻(上 、下 、左 、右 )的陆地单元格 或跨过 grid 的边界。

返回网格中 无法 在任意次数的移动中离开网格边界的陆地单元格的数量。

示例 1:

输入:grid = \[0,0,0,0,1,0,1,0,0,1,1,0,0,0,0,0]

输出:3

解释:有三个 1 被 0 包围。一个 1 没有被包围,因为它在边界上。

示例 2:

输入:grid = \[0,1,1,0,0,0,1,0,0,0,1,0,0,0,0,0]

输出:0

解释:所有 1 都在边界上或可以到达边界。

提示:

  • m == grid.length
  • n == grid[i].length
  • 1 <= m, n <= 500
  • grid[i][j] 的值为 0 或 1

💡思路:DFS

本题要求找到不靠边的陆地面积,那么

  • 我们只要从周边找到陆地
  • 然后 通过 dfs 或者 bfs 将周边靠陆地且相邻的陆地 都变成海洋,
  • 然后再去重新遍历地图的时候,统计此时还剩下的陆地就可以了。

🍁代码:(C++、Java)

C++

cpp 复制代码
class Solution {
private:
    int dir[4][2] = {-1, 0, 0, -1, 1, 0, 0, 1}; // 保存四个方向
    int m = 0, n = 0;
    void dfs(int i, int j, vector<vector<int>>& grid){
        if(grid[i][j] == 0){ // 是海洋则返回
            return;
        }
        grid[i][j] = 0;
        for(int k = 0; k < 4; k++){ // 向四个方向遍历
            int nexti = i + dir[k][0];
            int nextj = j + dir[k][1];
            if(nexti < 0 || nexti >= m || nextj < 0 || nextj >= n) continue;
            dfs(nexti, nextj, grid);
        }
    }
public:
    int numEnclaves(vector<vector<int>>& grid) {
        m = grid.size();
        n = grid[0].size();
        // 从左侧边,和右侧边 向中间遍历
        for(int i = 0; i < m; i++){
            dfs(i, 0, grid);
            dfs(i, n - 1, grid);
        }
        // 从上边和下边 向中间遍历
        for(int i = 0; i < n; i++){
            dfs(0, i, grid);
            dfs(m - 1, i, grid);
        }
        //统计剩余陆地的面积
        int ans = 0;
        for(int i = 0; i < m; i++){
            for(int j = 0; j < n; j++){
                if(grid[i][j] == 1) ans++;
            }
        }
        return ans;
    }
};

Java

java 复制代码
class Solution {
    private int[][] dir = {{-1, 0}, {0, -1}, {1, 0}, {0, 1}}; // 四个方向
    int m = 0, n = 0;

    private void dfs(int i, int j, int[][] grid){
        if(grid[i][j] == 0) return;// 是海洋则返回
        grid[i][j] = 0;
        for(int k = 0; k < 4; k++){// 向四个方向遍历
            int nexti = i + dir[k][0];
            int nextj = j + dir[k][1];
            // 超过边界
            if(nexti < 0 || nexti >= m || nextj < 0 || nextj >= n) continue;
            dfs(nexti, nextj, grid);
        }
    }
    public int numEnclaves(int[][] grid) {
        m = grid.length;
        n = grid[0].length;
        // 从左侧边,和右侧边 向中间遍历
        for(int i = 0; i < m; i++){
            dfs(i, 0, grid);
            dfs(i, n - 1, grid);
        }
        // 从上边和下边 向中间遍历
        for(int j = 0; j < n; j++){
            dfs(0, j, grid);
            dfs(m - 1, j, grid);
        }
        //统计剩余陆地的面积
        int ans = 0;
        for(int i = 0; i < m; i++){
            for(int j = 0; j < n; j++){
                if(grid[i][j] == 1) ans++;
            }
        }
        return ans;
    }
}

🚀 运行结果:

🕔 复杂度分析:

  • 时间复杂度 : O ( m n ) O(mn) O(mn),其中m 和 n 分别是网格 grid 的行数和列数。深度优先搜索最多访问每个单元格一次,需要 O ( m n ) O(mn) O(mn) 的时间,遍历网格统计飞地的数量也需要 O ( m n ) O(mn) O(mn) 的时间。

  • 空间复杂度 : O ( m n ) O(mn) O(mn),空间复杂度主要取决于递归调用栈空间,最大空间复杂度是 O ( m n ) O(mn) O(mn)。

题目来源:力扣。

放弃一件事很容易,每天能坚持一件事一定很酷,一起每日一题吧!
关注我LeetCode主页 / CSDN---力扣专栏,每日更新!

注: 如有不足,欢迎指正!

相关推荐
Dream it possible!5 小时前
LeetCode 面试经典 150_多维动态规划_交错字符串(97_C++_中等)
算法·leetcode·面试·动态规划
心抵鹊6 小时前
算法之双指针系列(一)
算法·leetcode
十二6 小时前
【洛谷题解】P1083 [NOIP 2012 提高组] 借教室(二分答案 + 差分)
数据结构·c++·算法·蓝桥杯
小此方7 小时前
[算法实战论:动态规划]回文串问题的dp解法,回文串问题的母题,以及以此为基础的派生题
算法·动态规划
Pniubi8 小时前
力扣560.和为k的子数组
算法·leetcode·职场和发展
D e re k ZH8 小时前
C++ 从零入门(一):基础语法与程序结构
数据结构·c++·算法
Pniubi8 小时前
力扣438.找到字符串中所有字母异位词
算法·leetcode·职场和发展
東隅已逝,桑榆非晚11 小时前
算法6. 双指针法-查找总价格为目标的两个商品
c++·学习·算法
Eyfcom11 小时前
〖物联网终端实战 01〗UWB 室内高精度定位:仓储 AGV 与人员的厘米级轨迹追踪
物联网·算法·物流系统·快递系统·跨境物流快递系统·物联网终端实战
bro_Java66612 小时前
《排序的底层逻辑:比较、交换与分治》
java·算法·排序算法