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

题目

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;  // 初始化最大面积为0for (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;  // 初始化最大岛屿面积为0for (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;  // 当前岛屿面积初始化为1for (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.mzph.cn/news/145213.shtml

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

相关文章

如何安装clang-9,clang,clang++

# 制定要version9的clang sudo apt-get install clang-9 # 创建软链 sudo ln -s /usr/bin/clang-9 /usr/bin/clang sudo ln -s /usr/bin/clang-9 /usr/bin/clang如果你已经安装了 clang-9&#xff0c;那么 clang 已经包含在内。通常&#xff0c;clang 是 clang 的一个符号链接&…

【Liunx】部署WEB服务:Apache

【Liunx】部署WEB服务:Apache 概述Apache1.介绍2.Apache文件路径3.Apache详解(1)安装Apache(2)启动Apache(3)配置文件a.Apache主配置文件&#xff1a;vim /etc/httpd/conf/httpd.conf信息&#xff1a;b.基于主机头的虚拟主机 (4)开始演示&#xff1a;a.新建两个网站根目录b.分别…

DVWA - 4

文章目录 JavaScriptlowmedium JavaScript 前端攻击。token 不能由前端生成&#xff0c;js 很容易被攻击者获取&#xff0c;从而伪造 token。同样其他重要的参数也不能由前端生成。 low 不修改输入&#xff0c;点击提交报错: 根据提示改成 success&#xff0c;还是报错&…

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

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

4.1 Windows驱动开发:内核中进程与句柄互转

在内核开发中&#xff0c;经常需要进行进程和句柄之间的互相转换。进程通常由一个唯一的进程标识符&#xff08;PID&#xff09;来标识&#xff0c;而句柄是指对内核对象的引用。在Windows内核中&#xff0c;EProcess结构表示一个进程&#xff0c;而HANDLE是一个句柄。 为了实…

实时数仓-Flink使用总结

阿里云实时计算Flink版是阿里云基于Apache Flink构建的企业级、高性能实时大数据处理系统。具备一站式开发运维管理平台&#xff0c;支持作业开发、数据调试、运行与监控、自动调优、智能诊断等全生命周期能力。本期将对Flink的使用进行总结。 1. Flink产品回顾 阿里云实时计算…

python趣味编程-5分钟实现一个Flappy Bird游戏(含源码、步骤讲解)

Python 中的 Flappy Bird 游戏可以免费下载开源代码,它是为想要学习 Python 的初学者创建的。 该项目系统使用了 Pygame 和 Random 模块。 Pygame 是一组跨平台的 Python 模块,专为编写视频游戏而设计。 Python 中的 Flappy Bird 代码 – 项目信息 项目名称:Python 中的 Fl…

2023年中国骨质疏松治疗仪发展趋势分析:小型且智能将成为产品优化方向[图]

骨质疏松治疗仪利用磁场镇静止痛、消肿消炎的治疗作用迅速缓解患者腰背疼痛等骨质疏松临床症状。同时利用磁场的磁-电效应产生的感生电势和感生电流&#xff0c;改善骨的代谢和骨重建&#xff0c;通过抑制破骨细胞、促进成骨细胞的活性来阻止骨量丢失、提高骨密度。 骨质疏松治…

2023-2024 年适用于 Windows 电脑的顶级视频录制软件

想捕捉您正在在线观看的视频吗&#xff1f;使用网络摄像头录制视频会议以供日后参考。正在寻找可以完成这些任务的视频捕捉软件&#xff1f;这篇文章说明了一切。以下是一些适用于 Windows PC 的最佳视频录制工具。 什么是视频录制软件&#xff1f; 顾名思义&#xff0c;视频捕…

【Vue 本地项目运行https服务】

配置本地开发环境的https访问 1、下载证书生成库2、创建证书颁发机构3、创建证书4、创建成功后会有4个文件在我们项目根目录5、定位到ca.crt 文件所在在位置 双击 安装证书6、在vue.config.js中引入证书&#xff1b; 1、下载证书生成库 npm install -g mkcert2、创建证书颁发机…

openGauss学习笔记-123 openGauss 数据库管理-设置账本数据库-账本数据库概述

文章目录 openGauss学习笔记-123 openGauss 数据库管理-设置账本数据库-账本数据库概述123.1 背景信息123.2 操作步骤 openGauss学习笔记-123 openGauss 数据库管理-设置账本数据库-账本数据库概述 123.1 背景信息 账本数据库融合了区块链思想&#xff0c;将用户操作记录至两…

合肥数字孪生赋能工业制造,加速推进制造业数字化转型

聚焦国家战略需求和先进制造业发展方向&#xff0c;加快数字化发展战略部署&#xff0c;数字孪生、工业互联网、工业物联网已被广泛认为是工业革命的新引擎。合肥数字孪生正在推动工业制造从制造转向智造。通过数字化建模和仿真的方式&#xff0c;优化设计、生产、质量管理、供…

Spring Task使用介绍

文章目录 Spring Task介绍cron表达式入门案例Spring Task使用步骤全注解的方式代码开发测试结果 代码仓库 Spring Task 介绍 Spring Task 是Spring框架提供的任务调度工具&#xff0c;可以按照约定的时间自动执行某个代码逻辑。 定位定时任务框架 作用定时自动执行某段Java…

centos的root密码忘记或失效的解决办法

目录 前言1 单机维护模式2 利用具有管理员权限的用户切换到root用户3 救援模式 前言 在Linux系统中&#xff0c;root用户是最高权限的用户&#xff0c;可以执行任何命令和操作。但是&#xff0c;如果我们忘记了root用户的密码&#xff0c;或者需要修改root用户的密码&#xff…

.NET8.0 AOT 经验分享 FreeSql/FreeRedis/FreeScheduler 均已通过测试

2023年11月15日&#xff0c;对.net的开发圈是一个重大的日子&#xff0c;.net 8.0正式版发布。 圈内已经预热了有半个月有余&#xff0c;性能不断超越&#xff0c;开发体验越来越完美&#xff0c;早在.net 5.0的时候就各种吹风Aot编译&#xff0c;直到6.0 7.0使用仍然比较麻烦…

什么是PWA(Progressive Web App)?它有哪些特点和优势?

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…

【PB续命05】WinHttp.WinHttpRequest的介绍与使用

0 WinHttp.WinHttpRequest简介 winhttp.winhttprequest是Windows操作系统中的一个API函数&#xff0c;用于创建和发送HTTP请求。它可以用于从Web服务器获取数据&#xff0c;或将数据发送到Web服务器。该函数提供了许多选项&#xff0c;例如设置请求头、设置代理服务器、设置超…

Js:获取最近6个月的月份(包含本月、不包含本月)

一、需求 获取最近6个月的月份&#xff08;不包含本月&#xff09;&#xff0c;比如现在是11月份&#xff0c;则需要获取到的月份是&#xff1a;10、9、8、7、6、5将月份从小到大排列 二、解决 1、获取最近的6个月份&#xff08;不包含本月&#xff09; var monthALL[]; …

Excel-快速将公式运用到一整列

先在该列的第一个单元格里写好公式&#xff0c;然后单击该单元格 在图中标示的地方输入我们需要填充的单元格区域 同时按住Ctrl和Enter键&#xff0c;这时需要填充的单元格区域就都被选中了 然后单击一下图中公式的后面&#xff0c;再次按下Ctrl和Enter键&#xff0c;这样就完…

注册表单mvc

jsp给我们的ControllerServlet 1在哪看到我们的数据呢 2什么时候用了session,有什么用 register.jsp 获取表单的name,email formBean.name是怎么定义的 3为什么就可以formbean访问 要使用的jsp对象都在servlet里面用setAttribute定义的 request.getSession().setAttribute…