【算法题解】53. 计封闭岛屿的数目

news2024/11/26 22:18:10

这是一道 中等难度 的题

https://leetcode.cn/problems/number-of-closed-islands/

题目

二维矩阵 grid 0 0 0(土地)和 1 1 1 (水)组成。岛是由最大的 4 4 4 个方向连通的 0 0 0 组成的群,封闭岛是一个 完全 1 1 1 包围(左、上、右、下)的岛。

请返回 封闭岛屿 的数目。

示例 1:

输入: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 区域包围)。

示例 2:

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

示例 3:

输入:grid = [
    		 [1,1,1,1,1,1,1],              
    		 [1,0,0,0,0,0,1],              
             [1,0,1,1,1,0,1],              
             [1,0,1,0,1,0,1],              
             [1,0,1,1,1,0,1],              
             [1,0,0,0,0,0,1],              
             [1,1,1,1,1,1,1]
            ] 
输出:2 

提示:

  • 1 < = g r i d . l e n g t h 1 <= grid.length 1<=grid.length, g r i d [ 0 ] . l e n g t h < = 100 grid[0].length <= 100 grid[0].length<=100
  • 0 < = g r i d [ i ] [ j ] < = 1 0 <= grid[i][j] <=1 0<=grid[i][j]<=1

题解

求岛屿数量也就是求数值为 0 的连通块。思路为遍历二维数组中的每一个元素,如果遇到 0 ,就说明遇到了岛屿,答案计数加一,然后一定要记得将这个岛屿覆盖到的所有 0 设置为 1 或其他 非0 的值,以免导致重复计数。

还有一点需要注意的是,题目要求的是 封闭岛屿,也就是不能包含挨着边界的外部连通块,所以在求内部连通块个数前可以先将外部连通块清除掉,清除方式同样是将所有 0 设置为 1

如何将岛屿覆盖到的所有 ‘0’ 设置为 ‘1’ 呢?

首先将当前位置 g r i d [ i ] [ j ] grid[i][j] grid[i][j]0 设置为 1,然后再将挨着这个位置的 上下左右 4个位置的 0 设置为 1,重复此步骤,每一步的处理逻辑都是一样的,又是典型的 递归 的思路。

递归函数: 将当前位置 g r i d [ i ] [ j ] grid[i][j] grid[i][j]0 设置为 1,然后再递归上下左右4个位置。

边界条件: 有两种可能,分别是:

  • i i i 或者 j j j 出界,返回。
  • g r i d [ i ] [ j ] = 1 grid[i][j] = 1 grid[i][j]=1,返回。

翻译成代码,以 Java 为例

// 递归函数,i 和 j 为当前位置的坐标
private void resetZero(int[][] grid, int i, int j){

    // 边界条件
    if(i < 0 || i >= grid.length){
        return;
    }
    if(j < 0 || j >= grid[0].length){
        return;
    }
    if(grid[i][j] == 1){
        return;
    }
        
	// 将当前位置设置为1
    grid[i][j] = 1;

    // 递归 上下左右 4个位置
    resetZero(grid, i + 1, j, m, n);
    resetZero(grid, i - 1, j, m, n);
    resetZero(grid, i, j + 1, m, n);
    resetZero(grid, i, j - 1, m, n);
}

综上,总体思路为:

  1. 循环遍历 4 条边,遇到 0 就使用递归函数 r e s e t Z e r o resetZero resetZero 将这个 0 所属于的外部连通块清除掉。
  2. 循环遍历 4 条边以内的所有点,遇到 0 就将答案 ans 加一,并将这个 0 所属于的内部连通块清除掉。

Java 代码实现

class Solution {
    public int closedIsland(int[][] grid) {
        // 先把边上的0和其联通的消除掉
        
        int m = grid.length;
        int n = grid[0].length;
        
        for(int i = 0; i < m; i++){
            // i = 0 或者 i = m - 1 或者 j = 0 或者 j = n - 1 时是边
            int step =  i == 0 || i == m - 1 ? 1 : n - 1;
            for(int j = 0; j < n; j += step){
                resetZero(grid, i, j);
            }
        }

        int ans = 0;
        for(int i = 1; i < m - 1; i++){
            for(int j = 1; j < n - 1; j++){
                // 遇到 0,答案就+1;
                // 然后将这个岛清除掉
                if(grid[i][j] == 0){
                    ans++;
                    resetZero(grid, i, j);
                }
            }
        }
        return ans;
    }

    private void resetZero(int[][] grid, int i, int j){

        if(i < 0 || i >= grid.length){
            return;
        }
        if(j < 0 || j >= grid[0].length){
            return;
        }
        if(grid[i][j] == 1){
            return;
        }
        

        grid[i][j] = 1;
        resetZero(grid, i + 1, j);
        resetZero(grid, i - 1, j);
        resetZero(grid, i, j + 1);
        resetZero(grid, i, j - 1);
    }
}

Go 代码实现

func closedIsland(grid [][]int) int {
    m, n := len(grid), len(grid[0])

    for i := 0; i < m; i++ {
        step := 1
        if i != 0 && i != m - 1 {
            step = n - 1
        }
        for j := 0; j < n; j += step {
            resetZero(grid, i, j)
        }
    }

    ans := 0
    for i := 1; i < m - 1; i++ {
        for j := 1; j < n - 1; j++ {
            if grid[i][j] == 0 {
                ans++
            }
            resetZero(grid, i, j)
        }
    }

    return ans
}

func resetZero(grid [][]int, i int, j int) {
    m, n := len(grid), len(grid[0])
    if i < 0 || i >= m || j < 0 || j >= n {
        return
    }
    if grid[i][j] == 1 {
        return
    }

    grid[i][j] = 1

    resetZero(grid, i + 1, j)
    resetZero(grid, i - 1, j)
    resetZero(grid, i, j - 1)
    resetZero(grid, i, j + 1)

}

复杂度分析

时间复杂度: O ( M N ) O(MN) O(MN)MN 分别为二维矩阵的高度和宽度。矩阵中的每一个为 1 的点都需要遍历 1 次。 每个为 0 的点需要遍历最多两次,一次是将 0 改为 1,一次是按顺序遍历检查是否是 0

空间复杂度: O ( M N ) O(MN) O(MN)MN 分别为二维矩阵的高度和宽度。空间复杂度取决于递归调用栈的深度,最大为 MN,即举矩阵中都是 0 的时候。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/872212.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用shift关键字,写一个带二级命令的脚本(如:docker run -a -b -c中的run)

省流&#xff1a;shift关键字 探索思路 最近有一个小小的需求&#xff0c;写一个类似于docker run -a -b -c这样的脚本&#xff0c;这个脚本名为doline&#xff0c;它本身可以执行&#xff08;doline -a -b -c&#xff09;&#xff0c;同时又带有几个如run、init、start这样的…

【Pytroch】基于K邻近算法的数据分类预测(Excel可直接替换数据)

【Pytroch】基于K邻近算法的数据分类预测&#xff08;Excel可直接替换数据&#xff09; 1.模型原理2.数学公式3.文件结构4.Excel数据5.下载地址6.完整代码7.运行结果 1.模型原理 K最近邻&#xff08;K-Nearest Neighbors&#xff0c;简称KNN&#xff09;是一种简单但常用的机器…

python编程基础与案例集锦,python编程入门经典

大家好&#xff0c;本文将围绕python编程基础与案例集锦展开说明&#xff0c;python编程入门与案例详解是一个很多人都想弄明白的事情&#xff0c;想搞清楚python入门程序例子需要先了解以下几个事情。 【程序1】 题目&#xff1a;输入一行字符&#xff0c;分别统计出其中英文字…

【c++】七夕快到了却还没对象?手把手教你new一个出来!

前言 本章给大家带来的是C内存管理。在C语言阶段&#xff0c;我们经常使用malloc&#xff0c;calloc&#xff0c;realloc&#xff0c;free进行内存管理。但是&#xff0c;C语言的内存管理存在很多缺陷&#xff0c;会对程序的稳定性和安全性造成影响。 不过&#xff0c;C语言的…

cubemx hal stm32 舵机 可减速 任意位置停止 驱动代码

CubeMX配置 对于 STM32 F407VE 这里的84是来自APB1那路2倍频得到&#xff1a; 代码部分 两个舵机都是180度的 servo.c #include "servo.h" #include "tim.h" #include "stdio.h"__IO uint32_t g_SteerUWT[2] {0}; uint16_t g_SteerDeg[…

开发一个RISC-V上的操作系统(七)—— 硬件定时器(Hardware Timer)

目录 往期文章传送门 一、硬件定时器 硬件实现 软件实现 二、上板测试 往期文章传送门 开发一个RISC-V上的操作系统&#xff08;一&#xff09;—— 环境搭建_riscv开发环境_Patarw_Li的博客-CSDN博客 开发一个RISC-V上的操作系统&#xff08;二&#xff09;—— 系统引导…

Monkey测试真的靠谱吗?

Monkey测试&#xff0c;顾名思义&#xff0c;就是模拟一只猴子在键盘上乱敲&#xff0c;从而达到测试被测系统的稳定性。Monkey测试&#xff0c;是Android自动化测试的一种手段&#xff0c;Monkey测试本身非常简单&#xff0c;Android SDK 工具支持adb Shell命令&#xff0c;实…

jvm里的内存溢出

目录 堆溢出 虚拟机栈和本地方法栈溢出&#xff08;栈溢出很少出现&#xff09; 方法区和运行时常量池溢出 本机内存直接溢出&#xff08;实际中很少出现、了解即可&#xff09; 堆溢出 堆溢出&#xff1a;最常见的是大list&#xff0c;list里面有很多元素 堆溢出该怎么解决…

C++红黑树

一、红黑树的概念 红黑树是一种二叉搜索树&#xff0c;在其每个节点上增加一个存储位用于表示节点的颜色&#xff0c;可以是Red或Black 通过对任何一条从根到叶子的路径上的各个节点着色方式的限制&#xff0c;红黑树确保没有一条路径比其他路径长两倍 红黑树的性质&#xff…

SQL | 汇总数据

9-汇总数据 9.1-聚集函数 在实际开发过程中&#xff0c;可能会遇到下面这些情况&#xff1a; 确定大于某个值的有多少行数据&#xff0c;比如游戏排行榜&#xff0c;查询玩家排行多少名。 获取表中某些行的和&#xff0c;比如双十一当天&#xff0c;某个用户总订单价格是多少…

208、仿真-51单片机脉搏心率与心电报警Proteus仿真设计(程序+Proteus仿真+配套资料等)

毕设帮助、开题指导、技术解答(有偿)见文未 目录 一、硬件设计 二、设计功能 三、Proteus仿真图 四、程序源码 资料包括&#xff1a; 需要完整的资料可以点击下面的名片加下我&#xff0c;找我要资源压缩包的百度网盘下载地址及提取码。 方案选择 单片机的选择 方案一&a…

回归预测 | MATLAB实现基于PSO-LSSVM-Adaboost粒子群算法优化最小二乘支持向量机结合AdaBoost多输入单输出回归预测

回归预测 | MATLAB实现基于PSO-LSSVM-Adaboost粒子群算法优化最小二乘支持向量机结合AdaBoost多输入单输出回归预测 目录 回归预测 | MATLAB实现基于PSO-LSSVM-Adaboost粒子群算法优化最小二乘支持向量机结合AdaBoost多输入单输出回归预测预测效果基本介绍模型描述程序设计参考…

MySQL8安装和删除教程 保姆级(Windows)

下载 官网: mysql官网点击Downloads->MySQL Community(GPL) Downloads->MySQL Community Server(或者点击MySQL installer for Windows) Windows下有两种安装方式 在线安装 一般带有 web字样 这个需要联网离线安装 一般没有web字样 安装 下载好之后,版本号可以不一样&…

Web 自动化测试学会这一招,下班至少早一小时

♥ 前 言 大家都知道&#xff0c;我们在通过 Selenium 执行 Web 自动化测试时&#xff0c;每次都需要启动/关闭浏览器&#xff0c;如果是多线程执行还会同时打开多个&#xff0c;比较影响工作的正常进行。那有没有办法可以不用让浏览器的自动化执行干扰我们的工作呢&#xf…

graphab 教程 ——生成廊道

Graphab软件包括图谱创建、基于图谱的连通性计算、分析与推广、制图四个模块。Graphab软件的图谱创建基于栅格数据进行,包括斑块识别和连接建立两个步骤。Graphab 软件可识别的栅格数据格式包括TIFF、ASCI和RST,栅格像元记录数值用于识别斑块类型,识别规则可以选择四邻域或八邻…

B100-技能提升-线程池分布式锁

目录 线程池什么是线程池&#xff1f;为什么用线程池?线程池原理常见四种线程池和自定义线程池 线程池 什么是线程池&#xff1f; 池化技术 为什么用线程池? 1 由于设置最大线程数&#xff0c;防止线程过多而导致系统崩溃。 2 线程复用&#xff0c;不需要频繁创建或销毁…

WebAPIs 第三天

DOM 事件进阶 事件流事件委托其他事件元素尺寸与位置 一.事件流 事件流与两个阶段说明事件捕获事件冒泡阻止冒泡解绑事件 1.1 事件流与两个阶段说明 ① 事件流&#xff1a;指的是事件完整执行过程中的流动路径 ② 事件流分为捕获阶段和冒泡阶段 1.2 事件捕获 从DOM根元素…

opsForHash() 与 opsForValue 请问有什么区别?

&#x1f449;&#xff1a;&#x1f517;官方API参考手册 如图&#xff0c;opsForHash()返回HashOperations<K,HK,HV>但是 opsForValue()返回ValueOperations<K,V>… 区别就是opsForHash的返回值泛型中有K,HK,HV,其中K是Redis指定的某个数据库里面某一个关键字(由…

三分钟带你快速掌握MongoDB数据库和集合基础操作

文章目录 前言一、案例需求二、数据库操作1. 选择和创建数据库2. 数据库的删除 三、集合操作1. 集合的显式创建&#xff08;了解&#xff09;2. 集合的隐式创建3. 集合的删除 总结 前言 为了巩固所学的知识&#xff0c;作者尝试着开始发布一些学习笔记类的博客&#xff0c;方便…

太牛了!国内版ChatDoc企业知识库,直接操作Doc、Docx、PDF、txt等文件

自ChatGPT问世以来&#xff0c;国外就有ChatPDF、ChatDOC等基于文档问答的项目&#xff0c;但是国内还一直处于对话类产品的研发中。 贵州猿创科技研发了基于本地向量模型的ChatDoc知识库系统&#xff0c;可以直接上传Doc、Docx、PDF、txt、网页链接等进行问答。 体验地址&…