力扣第695题 岛屿的最大面积 C++ DFS BFS 附Java代码

news2024/11/28 14:33:25

题目

695. 岛屿的最大面积

中等

相关标签

深度优先搜索   广度优先搜索   并查集   数组   矩阵

给你一个大小为 m x n 的二进制矩阵 grid 。

岛屿 是由一些相邻的 1 (代表土地) 构成的组合,这里的「相邻」要求两个 1 必须在 水平或者竖直的四个方向上 相邻。你可以假设 grid 的四个边缘都被 0(代表水)包围着。

岛屿的面积是岛上值为 1 的单元格的数目。

计算并返回 grid 中最大的岛屿面积。如果没有岛屿,则返回面积为 0 。

示例 1:

输入:grid = [[0,0,1,0,0,0,0,1,0,0,0,0,0],[0,0,0,0,0,0,0,1,1,1,0,0,0],[0,1,1,0,1,0,0,0,0,0,0,0,0],[0,1,0,0,1,1,0,0,1,0,1,0,0],[0,1,0,0,1,1,0,0,1,1,1,0,0],[0,0,0,0,0,0,0,0,0,0,1,0,0],[0,0,0,0,0,0,0,1,1,1,0,0,0],[0,0,0,0,0,0,0,1,1,0,0,0,0]]
输出:6
解释:答案不应该是 11 ,因为岛屿只能包含水平或垂直这四个方向上的 1。

示例 2:

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

提示:

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

思路和解题方法 1 DFS

  1. dfs 函数通过传入的坐标 (x, y) 来探索当前陆地区域的情况。如果当前坐标越界(超出了网格范围)或者是海洋(值为 0),则返回面积 0,表示此处不是陆地。

  2. 如果当前坐标是陆地(值为 1),则将其标记为已访问过(即将值置为 0),以免重复访问同一块陆地。然后开始向当前位置的上、下、左、右四个方向进行深度优先搜索,探索与当前陆地相连的其他陆地。

  3. 在每一步深度优先搜索中,我们累加当前陆地的面积,并递归地探索相邻的陆地。这样,通过深度优先搜索,我们能够计算出以当前位置为起点的整个连通陆地区域的面积。

  4. 最后,将累计的面积作为返回值返回给上一级递归调用。

maxAreaOfIsland 函数中,我们遍历整个网格,对于每个岛屿的起始位置(即值为 1 的位置),调用 dfs 函数来计算以该位置为起点的岛屿的面积。并将得到的面积与当前记录的最大面积进行比较,并更新最大面积的值。

时间复杂度分析:

  • 对于每个格子,最坏情况下需要进行深度优先搜索,而深度优先搜索的时间复杂度是 O(m*n),其中 m 和 n 分别为 grid 的行数和列数。
  • 因此,总的时间复杂度为 O(m*n),其中 m 为 grid 的行数,n 为 grid 的列数。

空间复杂度分析:

  • 深度优先搜索过程中使用的递归调用栈的最大深度为岛屿的大小,最坏情况下为整个 grid 大小,因此空间复杂度为 O(m*n)。
  • 此外,还需要考虑输入参数和一些辅助变量的空间占用,但是这些空间占用都是常数级别的,因此不影响总体的空间复杂度。

综上所述,该算法的时间复杂度为 O(mn),空间复杂度也为 O(mn)。

c++ 代码

class Solution {
public:
    // 深度优先搜索函数,用于搜索连通的岛屿区域并返回面积
    int dfs(vector<vector<int>>& grid, int x, int y) {
        // 递归终止条件
        if (x < 0 || x == grid.size() || y < 0 || y == grid[0].size() || grid[x][y] == 0) return 0;
        
        grid[x][y] = 0; // 将已经搜索过的陆地置为0,防止重复搜索(即将其视为沉没的岛屿)
        int ans = 1;
        // 分别搜索当前陆地的上、下、右、左四个方向的区块
        ans += dfs(grid, x, y + 1); // 上面
        ans += dfs(grid, x, y - 1); // 下面
        ans += dfs(grid, x + 1, y); // 右边
        ans += dfs(grid, x - 1, y); // 左边

        return ans;  // 返回当前连通岛屿的总面积
    }

    // 计算最大岛屿面积的函数
    int maxAreaOfIsland(vector<vector<int>>& grid) {
        int ans = 0;  // 初始化最大面积为0
        for (int i = 0; i != grid.size(); ++i) {
            for (int j = 0; j != grid[0].size(); ++j) {
                if (grid[i][j] == 1) {  // 如果当前位置是陆地
                    int cnt = dfs(grid, i, j);  // 对当前的岛屿区域进行深度优先搜索,得到面积
                    ans = max(ans, cnt);  // 更新最大面积
                }
            }
        }
        return ans;  // 返回最大岛屿面积
    }
};

思路和解题方法 2 BFS

  1. 首先,定义了一个类 Solution,其中包含了一个公有函数 maxAreaOfIsland,该函数接收一个二维向量 grid 作为参数,并返回岛屿的最大面积。

  2. maxAreaOfIsland 函数中,我们首先初始化 ans 为 0,以便记录最大的岛屿面积。

  3. 接下来是两个嵌套的 for 循环,用来遍历整个二维网格 grid

  4. 在每次迭代中,我们首先初始化 cur 为 0,用于记录当前岛屿的面积。然后创建两个队列 queueiqueuej,用于存储待访问的陆地坐标。

  5. 将当前遍历到的位置 (i, j) 入队,即将它们分别加入到 queueiqueuej 中。

  6. 进入while循环,只要队列非空,就不断进行以下操作:

    • 弹出队首的坐标 (cur_i, cur_j)
    • 检查当前坐标是否越界或者不是陆地,若是则跳过本次循环;
    • 若当前坐标是陆地,则将当前面积 cur 自增,并将当前坐标标记为已访问过的海洋(即将值置为 0),然后探索当前位置的上、下、左、右四个方向;
    • 将相邻的陆地坐标入队。
  7. 在每次内部循环结束时,更新 ans 为当前 curans 之间的较大值。

  8. 最后,遍历结束后返回 ans,即为岛屿的最大面积。

时间复杂度分析:

  • 时间复杂度取决于岛屿的数量和网格的大小。假设网格的行数为 m,列数为 n,岛屿的数量为 k,那么时间复杂度可以表示为 O(mn+k),其中 mn 表示遍历整个网格的时间复杂度,k 表示计算岛屿面积的时间复杂度。

空间复杂度分析:

  • 空间复杂度方面,使用了两个队列 queueiqueuej,它们的最大长度可以达到网格的面积大小,因此空间复杂度也是 O(m*n)。

综上所述,该算法的时间复杂度为 O(mn),空间复杂度也为 O(mn)。

c++ 代码

class Solution {
public:
    int maxAreaOfIsland(vector<vector<int>>& grid) {
        int ans = 0;
        // 遍历二维网格的每一个位置
        for (int i = 0; i != grid.size(); ++i) {
            for (int j = 0; j != grid[0].size(); ++j) {
                int cur = 0;  // 当前岛屿的面积
                queue<int> queuei;
                queue<int> queuej;
                queuei.push(i);  // 将当前位置加入队列
                queuej.push(j);
                while (!queuei.empty()) {
                    int cur_i = queuei.front(), cur_j = queuej.front();  // 取出队首元素
                    queuei.pop();
                    queuej.pop();
                    if (cur_i < 0 || cur_j < 0 || cur_i == grid.size() || cur_j == grid[0].size() || grid[cur_i][cur_j] != 1) {
                        continue;  // 如果当前位置超出边界或者不是岛屿,跳过
                    }
                    ++cur;  // 当前岛屿面积加一
                    grid[cur_i][cur_j] = 0;  // 将当前位置置为0,表示已经访问过
                    int di[4] = {0, 0, 1, -1};  // 方向数组,表示上下左右四个方向
                    int dj[4] = {1, -1, 0, 0};
                    for (int index = 0; index != 4; ++index) {
                        int next_i = cur_i + di[index], next_j = cur_j + dj[index];  // 计算四个相邻位置
                        queuei.push(next_i);  // 将相邻位置加入队列
                        queuej.push(next_j);
                    }
                }
                ans = max(ans, cur);  // 更新最大岛屿面积
            }
        }
        return ans;  // 返回最大岛屿面积
    }
};

附Java代码

DFS

class Solution {
    public int maxAreaOfIsland(int[][] grid) {
        int ans = 0;  // 初始化最大岛屿面积为0
        for (int i = 0; i != grid.length; ++i) {  // 遍历二维网格的每一个位置
            for (int j = 0; j != grid[0].length; ++j) {
                ans = Math.max(ans, dfs(grid, i, j));  // 计算以当前位置为起点的岛屿面积,并更新最大值
            }
        }
        return ans;  // 返回最大岛屿面积
    }

    public int dfs(int[][] grid, int cur_i, int cur_j) {
        if (cur_i < 0 || cur_j < 0 || cur_i == grid.length || cur_j == grid[0].length || grid[cur_i][cur_j] != 1) {
            return 0;  // 如果当前位置超出边界或者不是岛屿,返回面积为0
        }
        grid[cur_i][cur_j] = 0;  // 将当前位置置为0,表示已经访问过
        int[] di = {0, 0, 1, -1};  // 方向数组,表示上下左右四个方向
        int[] dj = {1, -1, 0, 0};
        int ans = 1;  // 当前岛屿面积初始化为1
        for (int index = 0; index != 4; ++index) {
            int next_i = cur_i + di[index], next_j = cur_j + dj[index];  // 计算四个相邻位置
            ans += dfs(grid, next_i, next_j);  // 递归计算相邻位置的岛屿面积并累加
        }
        return ans;  // 返回当前岛屿面积
    }
}

BFS

class Solution {
    // 计算岛屿的最大面积
    public int maxAreaOfIsland(int[][] grid) {
        int ans = 0;  // 初始化最大面积为 0
        // 遍历整个网格
        for (int i = 0; i != grid.length; ++i) {
            for (int j = 0; j != grid[0].length; ++j) {
                int cur = 0;  // 当前岛屿的面积
                Queue<Integer> queuei = new LinkedList<Integer>();  // 存储陆地坐标的队列
                Queue<Integer> queuej = new LinkedList<Integer>();  // 存储陆地坐标的队列
                queuei.offer(i);  // 将当前坐标入队
                queuej.offer(j);  // 将当前坐标入队
                // BFS 遍历岛屿
                while (!queuei.isEmpty()) {
                    int cur_i = queuei.poll(), cur_j = queuej.poll();  // 出队当前坐标
                    // 检查当前坐标是否越界或者不是陆地,若是则跳过本次循环
                    if (cur_i < 0 || cur_j < 0 || cur_i == grid.length || cur_j == grid[0].length || grid[cur_i][cur_j] != 1) {
                        continue;
                    }
                    ++cur;  // 当前岛屿的面积加一
                    grid[cur_i][cur_j] = 0;  // 标记当前坐标为已访问过的海洋
                    int[] di = {0, 0, 1, -1};  // 方向数组,分别表示上、下、左、右四个方向
                    int[] dj = {1, -1, 0, 0};  // 方向数组,分别表示上、下、左、右四个方向
                    // 探索当前位置的上、下、左、右四个方向
                    for (int index = 0; index != 4; ++index) {
                        int next_i = cur_i + di[index], next_j = cur_j + dj[index];  // 计算相邻坐标
                        queuei.offer(next_i);  // 将相邻的陆地坐标入队
                        queuej.offer(next_j);  // 将相邻的陆地坐标入队
                    }
                }
                ans = Math.max(ans, cur);  // 更新最大面积
            }
        }
        return ans;  // 返回岛屿的最大面积
    }
}

觉得有用的话可以点点赞,支持一下。

如果愿意的话关注一下。会对你有更多的帮助。

每天都会不定时更新哦  >人<  。

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

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

相关文章

系列四、JVM的内存结构【本地接口(Native Interface)】

一、组成 本地接口由本地方法栈&#xff08;Native Method Stack&#xff09;、本地方法接口&#xff08;Native Interface&#xff09;、本地方法库组成。 二、本地接口的作用 本地接口的作用是融合不同的编程语言为Java所用&#xff0c;它的初衷是融合C/C程序&#xff0c;Jav…

CTFhub-RCE-过滤运算符

检查网页源代码发现如果用户输入 || &#xff08;逻辑或操作符&#xff09; 或者是 & &#xff08;按位与操作符&#xff09;&#xff0c;就不会执行。直接进行测试&#xff0c;在 URL 后输入本地 IP 进行 ping 命令测试&#xff0c;发现可以正常回显。检查网页源代码发现如…

C++基础从0到1入门编程(一)

系统学习C 方便自己日后复习&#xff0c;错误的地方希望积极指正 参考视频&#xff1a;黑马程序员匠心之作|C教程从0到1入门编程,学习编程不再难 1 第一个C程序-HelloWorld 编写一个C程序分为四个步骤&#xff1a; &#xff08;1&#xff09;创建项目 &#xff08;2&#xff…

Android开发APP显示头部Bar

Android开发显示头部Bar 需求&#xff1a; 显示如下图&#xff1a; 显示头部Bar&#xff0c;颜色也能自定义。 解决方案 这个修改是在如下三个文件里进行修改&#xff1a; 按顺序修改&#xff1a; themes.xml(night): <resources xmlns:tools"http://schemas.andr…

LeetCode(22)N 字形变换【数组/字符串】【中等】

目录 1.题目2.答案3.提交结果截图 链接&#xff1a; N 字形变换 1.题目 将一个给定字符串 s 根据给定的行数 numRows &#xff0c;以从上往下、从左到右进行 Z 字形排列。 比如输入字符串为 "PAYPALISHIRING" 行数为 3 时&#xff0c;排列如下&#xff1a; P A …

3.6 Windows驱动开发:内核进程汇编与反汇编

在笔者上一篇文章《内核MDL读写进程内存》简单介绍了如何通过MDL映射的方式实现进程读写操作&#xff0c;本章将通过如上案例实现远程进程反汇编功能&#xff0c;此类功能也是ARK工具中最常见的功能之一&#xff0c;通常此类功能的实现分为两部分&#xff0c;内核部分只负责读写…

滚雪球学Java(09-2):Java中的关系运算符,你真的掌握了吗?

咦咦咦&#xff0c;各位小可爱&#xff0c;我是你们的好伙伴——bug菌&#xff0c;今天又来给大家普及Java SE相关知识点了&#xff0c;别躲起来啊&#xff0c;听我讲干货还不快点赞&#xff0c;赞多了我就有动力讲得更嗨啦&#xff01;所以呀&#xff0c;养成先点赞后阅读的好…

java“贪吃蛇”小游戏

基于java实现贪吃蛇小游戏&#xff0c;主要通过绘制不同的图片并以一定速度一帧一帧地在窗体上进行展示。 我是在javaSwing项目下创建了一个包 名字叫做&#xff1a;Snakes包 包下有一个启动类和一个设置代码的主界面两个类 代码主界面&#xff1a; 代码主界面主要讲解的是 …

2023年中国冲击波治疗仪市场发展趋势分析:未来市场增长空间更大[图]

冲击波在临床医学领域最早应用于体外冲击波碎石&#xff0c;在二十世纪八十年代末期&#xff0c;体外冲击波碎石技术开始被运用到骨科及康复理疗领域&#xff0c;经过十余年的临床研究&#xff0c;冲击波疗法日益完善&#xff0c;应用范围也日益扩大。冲击波作为一种介于保守疗…

【Linux】Linux进程间通信(二)

​ ​&#x1f4dd;个人主页&#xff1a;Sherry的成长之路 &#x1f3e0;学习社区&#xff1a;Sherry的成长之路&#xff08;个人社区&#xff09; &#x1f4d6;专栏链接&#xff1a;Linux &#x1f3af;长路漫漫浩浩&#xff0c;万事皆有期待 上一篇博客&#xff1a;【Linux】…

【开源】基于Vue和SpringBoot的固始鹅块销售系统

项目编号&#xff1a; S 060 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S060&#xff0c;文末获取源码。} 项目编号&#xff1a;S060&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 鹅块类型模块2.3 固…

Elasticsearch:运用向量搜索通过图像搜索找到你的小狗

作者&#xff1a;ALEX SALGADO 你是否曾经遇到过这样的情况&#xff1a;你在街上发现了一只丢失的小狗&#xff0c;但不知道它是否有主人&#xff1f; 了解如何使用向量搜索或图像搜索来做到这一点。 通过图像搜索找到你的小狗 您是否曾经遇到过这样的情况&#xff1a;你在街…

【自留地】前端 - uniapp - Vue - React - Flutter

uniapp uniapp自用速查表 - 我的常用组件 uniapp自用速查表 - 我的常用组件_uniapp static/customicons.css-CSDN博客文章浏览阅读1.8k次。uniapp项目登录退出、全局变量与状态、本地存储、Tabbar标签栏、顶部导航栏、下拉刷新、触底刷新、Ajax交互、内置组件样式修改、自定义…

2018年五一杯数学建模C题江苏省本科教育质量综合评价解题全过程文档及程序

2019年五一杯数学建模 C题 江苏省本科教育质量综合评价 原题再现 随着中国的改革开放&#xff0c;国家的综合实力不断增强&#xff0c;中国高等教育发展整体已进入世界中上水平。作为一个教育大省&#xff0c;江苏省的本科教育发展在全国名列前茅&#xff0c;而江苏省13个地级…

Linux:进程替换和知识整合

文章目录 进程程序替换替换原理进程替换的理解 环境变量与进程替换命令行解释器实现逻辑 进程程序替换 前面已经学习了子进程的创建&#xff0c;但是子进程的创建不管怎么说&#xff0c;都是父进程代码的一部分&#xff0c;那么实际上如果想要子进程执行新的程序呢&#xff1f…

2023年中国脑电仿生电刺激仪发展趋势分析:智能化、精准化、使用感不断提高[图]

脑电仿生电刺激仪是一种通过直接数字频率合成技术合成脑电仿真低频生物电流&#xff0c;通过粘贴于两耳侧乳突、太阳穴或风池穴部位表皮的电极&#xff0c;用仿生物电自颅外无创伤地穿透颅骨屏障刺激小脑顶核区的电疗设备。此电流刺激可启动颅脑固有神经保护机制&#xff0c;改…

【MATLAB】史上最全的9种数据拟合算法全家桶

有意向获取代码&#xff0c;请转文末观看代码获取方式~ 大家吃一顿火锅的价格便可以拥有9种数据拟合算法&#xff0c;绝对不亏&#xff0c;知识付费是现今时代的趋势&#xff0c;而且都是我精心制作的教程&#xff0c;有问题可随时反馈~也可单独获取某一算法的代码&#xff08…

Odoo 15开发手册第六章 模型 - 结构化应用数据

本章我们更进一步学习模型层&#xff0c;以及如何使用模型来设计支撑应用的数据结构。我们会探讨可用的模型类型&#xff0c;以及在使用这些类型时如何定义强制进行数据验证的约束。 模型由支持不同数据类型的数据字段组成&#xff0c;一些字段类型支持定义模型间的关联。对于…

delphi电子处方流转 sm2 sm4(医院)

【delphi电子处方流转(医院) sm2 sm4】支持 就诊登记、电子处方上传预核验、处方处方医保电子签名、电子处方上传、电子处方撤销、电子处方信息查询、电子处方审核结果查询、电子处方取药结果查询、电子处方药品目录查询等功能。技术交流Q 648437169 下载链接&#xff1a;http…

4. hdfs高可用集群搭建

简介 前面把hadoop机器已经准备好了&#xff0c;zk集群搭建好了&#xff0c;本本就是开始搭建hdfs环境 hadoop环境准备 创建hadoop用户 三台机器都创建hadoop用户 useradd hadoop -d /home/hadoop echo "1q1w1e1r" | passwd --stdin hadoophadoop用户相互免密登…