代码随想录第五十二天| 101.孤岛的总面积 102.沉没孤岛 103.水流问题 104.建造最大岛屿

孤岛的总面积

题目描述

给定一个由 1(陆地)和 0(水)组成的矩阵,岛屿指的是由水平或垂直方向上相邻的陆地单元格组成的区域,且完全被水域单元格包围。孤岛是那些位于矩阵内部、所有单元格都不接触边缘的岛屿。现在你需要计算所有孤岛的总面积,岛屿面积的计算方式为组成岛屿的陆地的总数。

解题思路

  1. 标记边缘岛屿:首先遍历矩阵的边缘,如果发现陆地(1),则使用深度优先搜索(DFS)标记整个岛屿,这些岛屿不是孤岛。
  2. 计算孤岛面积:再次遍历矩阵,对于未被标记且是陆地的单元格,使用DFS计算其所在岛屿的面积,并将所有孤岛的面积累加。

代码实现

import java.util.*;public class Main {public static void main(String[] args) {Scanner sc = new Scanner(System.in);int m = sc.nextInt();int n = sc.nextInt();int[][] grid = new int[m][n];for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {grid[i][j] = sc.nextInt();}}boolean[][] visited = new boolean[m][n];// 标记边缘岛屿for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {if ((i == 0 || i == m - 1 || j == 0 || j == n - 1) && grid[i][j] == 1 && !visited[i][j]) {visited[i][j] = true;dfsMarkEdge(i, j, visited, grid);}}}int totalArea = 0;// 计算孤岛总面积for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {if (!visited[i][j] && grid[i][j] == 1) {visited[i][j] = true;totalArea += dfsCalculateArea(i, j, visited, grid);}}}System.out.println(totalArea);  }private static final int[][] directions = {{0, 1}, {1, 0}, {-1, 0}, {0, -1}};// DFS标记边缘岛屿public static void dfsMarkEdge(int x, int y, boolean[][] visited, int[][] grid) {for (int i = 0; i < 4; i++) {int nextX = x + directions[i][0];int nextY = y + directions[i][1];if (nextX < 0 || nextY < 0 || nextX >= grid.length || nextY >= grid[0].length) continue;if (!visited[nextX][nextY] && grid[nextX][nextY] == 1) {visited[nextX][nextY] = true;dfsMarkEdge(nextX, nextY, visited, grid);}}}// DFS计算孤岛面积public static int dfsCalculateArea(int x, int y, boolean[][] visited, int[][] grid) {int area = 1;for (int i = 0; i < 4; i++) {int nextX = x + directions[i][0];int nextY = y + directions[i][1];if (nextX < 0 || nextY < 0 || nextX >= grid.length || nextY >= grid[0].length) continue;if (!visited[nextX][nextY] && grid[nextX][nextY] == 1) {visited[nextX][nextY] = true;area += dfsCalculateArea(nextX, nextY, visited, grid);}}return area;}
}

沉没孤岛

题目描述

给定一个由 1(陆地)和 0(水)组成的矩阵,岛屿指的是由水平或垂直方向上相邻的陆地单元格组成的区域,且完全被水域单元格包围。孤岛是那些位于矩阵内部、所有单元格都不接触边缘的岛屿。现在你需要将所有孤岛“沉没”,即将孤岛中的所有陆地单元格(1)转变为水域单元格(0)。

解题思路

  1. 标记边缘岛屿:首先遍历矩阵的边缘,如果发现陆地(1),则使用深度优先搜索(DFS)标记整个岛屿,这些岛屿不是孤岛。
  2. 沉没孤岛:再次遍历矩阵,对于未被标记且是陆地的单元格,将其置为0,从而实现沉没孤岛。

代码实现

import java.util.*;public class Main {public static void main(String[] args) {Scanner sc = new Scanner(System.in);int m = sc.nextInt();int n = sc.nextInt();int[][] grid = new int[m][n];for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {grid[i][j] = sc.nextInt();}}boolean[][] visited = new boolean[m][n];// 标记边缘岛屿for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {if ((i == 0 || i == m - 1 || j == 0 || j == n - 1) && grid[i][j] == 1 && !visited[i][j]) {visited[i][j] = true;dfsMarkEdge(i, j, visited, grid);}}}// 沉没孤岛for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {if (!visited[i][j] && grid[i][j] == 1) {grid[i][j] = 0;}}}// 输出结果矩阵for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {System.out.print(grid[i][j] + " ");}System.out.println();}sc.close(); }private static final int[][] directions = {{0, 1}, {1, 0}, {-1, 0}, {0, -1}};// DFS标记边缘岛屿public static void dfsMarkEdge(int x, int y, boolean[][] visited, int[][] grid) {for (int i = 0; i < 4; i++) {int nextX = x + directions[i][0];int nextY = y + directions[i][1];if (nextX < 0 || nextY < 0 || nextX >= grid.length || nextY >= grid[0].length) continue;if (!visited[nextX][nextY] && grid[nextX][nextY] == 1) {visited[nextX][nextY] = true;dfsMarkEdge(nextX, nextY, visited, grid);}}}
}

水流问题

题目描述

现有一个 N × M 的矩阵,每个单元格包含一个数值,这个数值代表该位置的相对高度。矩阵的左边界和上边界被认为是第一组边界(太平洋),而矩阵的右边界和下边界被视为第二组边界(大西洋)。当雨水落在上面时,水会根据地形的倾斜向低处流动,但只能从较高或等高的地点流向较低或等高并且相邻(上下左右方向)的地点。我们的目标是确定那些单元格,从这些单元格出发的水可以达到第一组边界和第二组边界。

解题思路

  1. 双边界标记:分别从太平洋和大西洋的边界出发,使用深度优先搜索(DFS)标记所有能够流向对应边界的单元格。
    • 对于太平洋,遍历矩阵的左边界和上边界,从这些边界上的每个单元格开始 DFS,标记所有能流向太平洋的单元格。
    • 对于大西洋,遍历矩阵的右边界和下边界,从这些边界上的每个单元格开始 DFS,标记所有能流向大西洋的单元格。
  2. 结果收集:遍历整个矩阵,找出同时被太平洋和大西洋标记的单元格,这些单元格即为所求。

代码实现

import java.util.*;public class Main {public static void main(String[] args) {Scanner sc = new Scanner(System.in);int m = sc.nextInt();int n = sc.nextInt();int[][] grid = new int[m][n];for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {grid[i][j] = sc.nextInt();}}// 初始化两个二维 boolean 数组,分别代表能流向太平洋和大西洋的单元格boolean[][] pacific = new boolean[m][n];boolean[][] atlantic = new boolean[m][n];// 从太平洋边界出发进行 DFSfor (int i = 0; i < m; i++) {dfs(i, 0, pacific, grid, Integer.MIN_VALUE);}for (int j = 0; j < n; j++) {dfs(0, j, pacific, grid, Integer.MIN_VALUE);}// 从大西洋边界出发进行 DFSfor (int i = 0; i < m; i++) {dfs(i, n - 1, atlantic, grid, Integer.MIN_VALUE);}for (int j = 0; j < n; j++) {dfs(m - 1, j, atlantic, grid, Integer.MIN_VALUE);}// 收集结果List<List<Integer>> res = new ArrayList<>();for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {if (pacific[i][j] && atlantic[i][j]) {res.add(Arrays.asList(i, j));}}}// 输出结果for (List<Integer> list : res) {for (int k = 0; k < list.size(); k++) {if (k == 0) {System.out.print(list.get(k) + " ");} else {System.out.print(list.get(k));}}System.out.println();}sc.close(); }// DFS 函数,用于标记能流向指定边界的所有单元格public static void dfs(int x, int y, boolean[][] valid, int[][] grid, int preH) {if (x < 0 || y < 0 || x >= grid.length || y >= grid[0].length || valid[x][y]) return;if (grid[x][y] < preH) return;valid[x][y] = true;dfs(x + 1, y, valid, grid, grid[x][y]);dfs(x - 1, y, valid, grid, grid[x][y]);dfs(x, y + 1, valid, grid, grid[x][y]);dfs(x, y - 1, valid, grid, grid[x][y]);}
}

建造最大岛屿

题目描述

给定一个由 1(陆地)和 0(水)组成的矩阵,你最多可以将矩阵中的一格水变为一块陆地,在执行了此操作之后,矩阵中最大的岛屿面积是多少。岛屿面积的计算方式为组成岛屿的陆地的总数。岛屿是被水包围,并且通过水平方向或垂直方向上相邻的陆地连接而成的。你可以假设矩阵外均被水包围。

解题思路

  1. 预处理岛屿:首先遍历整个矩阵,使用深度优先搜索(DFS)标记每个岛屿,并记录每个岛屿的面积。
  2. 模拟填海:对于每个水域单元格,模拟将其变为陆地,然后检查其上下左右相邻的岛屿,计算这些岛屿合并后的总面积(包括当前填海的单元格)。
  3. 结果计算:在所有可能的填海位置中,找到最大的岛屿面积。

代码实现

import java.util.*;
import java.math.*;public class Main {private static final int[][] dir = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};public static void main(String[] args) {Scanner sc = new Scanner(System.in);int m = sc.nextInt();int n = sc.nextInt();int[][] grid = new int[m][n];for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {grid[i][j] = sc.nextInt();}}boolean[][] visited = new boolean[m][n];int mapnum = 1;int size = 0;HashMap<Integer, Integer> sizeMap = new HashMap<>();boolean isAllIsland = true;// 预处理所有岛屿for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {if (grid[i][j] == 0) isAllIsland = false;if (!visited[i][j] && grid[i][j] == 1) {visited[i][j] = true;grid[i][j] = mapnum;size = dfs(i, j, visited, grid, mapnum);sizeMap.put(mapnum, size);mapnum++;}}}int result = 0;HashSet<Integer> adjacentIslands = new HashSet<>();// 如果整个矩阵都是岛屿if (isAllIsland) {result = m * n;} else {// 遍历每个水域单元格,模拟填海for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {if (grid[i][j] == 0) {adjacentIslands.clear();int currentSize = 1; // 当前填海的单元格本身算1for (int z = 0; z < 4; z++) {int nextX = i + dir[z][0];int nextY = j + dir[z][1];if (nextX < 0 || nextY < 0 || nextX >= m || nextY >= n) continue;int neighborMark = grid[nextX][nextY];if (adjacentIslands.contains(neighborMark) || !sizeMap.containsKey(neighborMark)) continue;adjacentIslands.add(neighborMark);currentSize += sizeMap.get(neighborMark);}result = Math.max(currentSize, result);}}}}System.out.println(result);}// DFS 计算岛屿面积并标记public static int dfs(int x, int y, boolean[][] visited, int[][] grid, int mapnum) {int size = 1;for (int i = 0; i < 4; i++) {int nextX = x + dir[i][0];int nextY = y + dir[i][1];if (nextX < 0 || nextY < 0 || nextX >= grid.length || nextY >= grid[0].length) continue;if (!visited[nextX][nextY] && grid[nextX][nextY] == 1) {visited[nextX][nextY] = true;grid[nextX][nextY] = mapnum;size += dfs(nextX, nextY, visited, grid, mapnum);}}return size;}
}

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

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

相关文章

八叉树地图的原理与实现

八叉树与体素图 八叉树地图 八叉树地图是可变分辨率的三维栅格地图&#xff0c;可以自由调整分辨率&#xff0c;如下所示&#xff1a; 根据点云的数量或密度决定每个叶子方块是否被占据 体素图 体素就是固定分辨率的三维栅格地图&#xff0c;如下所示&#xff1a; 根据点云…

最节省服务器,手搓电子证书查询系统

用户预算150元&#xff0c;想要一个最简单证书查询系统。前台能查询证书、后台管理员能登录能修改密码&#xff0c;证书能够手动输入修改删除、批量导入导出删除数据、查询搜索。能够兼容苹果、安卓、PC三端浏览器&#xff0c;最后帮忙部署到云服务器上。 用户预算不多&#xf…

什么是全栈?

&#x1f91f;致敬读者 &#x1f7e9;感谢阅读&#x1f7e6;笑口常开&#x1f7ea;生日快乐⬛早点下班 &#x1f4d8;博主相关 &#x1f7e7;博主信息&#x1f7e8;博客首页&#x1f7eb;专栏推荐&#x1f7e5;活动信息 &#x1f4c3;文章前言 &#x1f537;文章均为学习工…

作物移栽机器人的结构设计的介绍

作物移栽机器人的结构设计是一个复杂的机械与电子结合的系统工程&#xff0c;单纯用代码来实现整个结构设计是不现实的&#xff0c;因为结构设计更多涉及到机械结构、硬件选型等物理层面的内容。不过&#xff0c;我们可以通过代码来模拟作物移栽机器人的部分功能&#xff0c;例…

【文献阅读】SPRec:用自我博弈打破大语言模型推荐的“同质化”困境

&#x1f4dc;研究背景 在如今的信息洪流中&#xff0c;推荐系统已经成为了我们生活中的“贴心小助手”&#xff0c;无论是看电影、听音乐还是购物&#xff0c;推荐系统都在努力为我们提供个性化的内容。但这些看似贴心的推荐背后&#xff0c;其实隐藏着一个严重的问题——同质…

使用1Panel一键搭建WordPress网站的详细教程(全)

嘿&#xff0c;各位想搭建自己网站的朋友们&#xff01;今天我要跟大家分享我用1Panel搭建WordPress网站的全过程。说实话&#xff0c;我之前对服务器运维一窍不通&#xff0c;但通过这次尝试&#xff0c;我发现原来建站可以这么简单&#xff01;下面是我的亲身经历和一些小技巧…

本地fake server,

C# 制作的系统级tcp 重定向&#xff0c;整个系统只要有访问指定url&#xff0c;返回自定义内容到访问端。不局限在浏览器单一方面。 再者请理解这个图的含金量&#xff0c;服务器down机都可以模拟。 用途那就太多了&#xff0c;当然很多用途都不正当。嘿嘿 如果你很想要源代…

设计模式之美

UML建模 统一建模语言&#xff08;UML&#xff09;是用来设计软件的可视化建模语言。它的语言特点是简单 统一 图形化 能表达软件设计中的动态与静态信息。 UML的分类 动态结构图&#xff1a; 类图 对象图 组件图 部署图 动态行为图&#xff1a; 状态图 活动图 时序图 协作…

【openGauss】物理备份恢复

文章目录 1. gs_backup&#xff08;1&#xff09;备份&#xff08;2&#xff09;恢复&#xff08;3&#xff09;手动恢复的办法 2. gs_basebackup&#xff08;1&#xff09;备份&#xff08;2&#xff09;恢复① 伪造数据目录丢失② 恢复 3. gs_probackup&#xff08;1&#xf…

一文了解JVM的垃圾回收

Java堆内存结构 java堆内存是垃圾回收器管理的主要区域&#xff0c;也被称为GC堆。 为了方便垃圾回收&#xff0c;堆内存被分为新生代、老年代和永久代。 新创建的对象的内存会在新生代中分配&#xff0c;达到一定存活时长后会移入老年代&#xff0c;而永久代存储的是类的元数…

SQL子查询与MyBatis映射

文章目录 前言1. 数据库表结构2. MyBatis Mapper XML3. Java 实体类4. 技术点解析5. 执行效果6. 优化建议 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 以下是一个结合 SQL 别名、子查询、MyBatis 字段映射和代码复用的完整案例&#xff0c;以用户管…

基于SpringBoot的“校园周边美食探索及分享平台”的设计与实现(源码+数据库+文档+PPT)

基于SpringBoot的“校园周边美食探索及分享平台”的设计与实现&#xff08;源码数据库文档PPT) 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBoot 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 校园周边美食探索及分享平台结构图…

时间复杂度(Time Complexity)

时间复杂度 1. 什么是时间复杂度&#xff1f; 时间复杂度&#xff08;Time Complexity&#xff09;是计算算法执行时间随输入规模&#xff08;n&#xff09;增长的变化趋势。它衡量算法的效率&#xff0c;通常使用大 O 记号&#xff08;Big-O notation&#xff09;表示&#…

树莓派:更新源

发行版本 Debian 一直维护着至少三个发行版本&#xff1a;“稳定版&#xff08;stable&#xff09;”&#xff0c;“测试版&#xff08;testing&#xff09;”和“不稳定版&#xff08;unstable&#xff09;”。 发行版目录 下一代 Debian 正式发行版的代号为 bullseye — 发布…

K8s 1.27.1 实战系列(八)Service

一、Service介绍 1、Service 的作用与核心功能 Service 是 Kubernetes 中用于抽象一组 Pod 并提供稳定访问入口的资源。它解决了以下问题: ​Pod IP 不固定:Pod 可能因故障、扩缩容或更新导致 IP 变化,Service 通过 ClusterIP(虚拟 IP)提供固定访问地址。​负载均衡:自动…

RocketMQ性能优化篇

在分布式消息系统中&#xff0c;RocketMQ以其高性能、高可靠性和高可扩展性而被广泛应用。然而&#xff0c;为了充分发挥其性能优势&#xff0c;需要进行一系列的性能测试和优化。本文将从性能测试方法和优化实践两个方面&#xff0c;详细介绍如何对RocketMQ进行性能优化。通过…

CSS 知识点总结1

CSS 知识点总结&#xff11; 今天写了两个页面,用到的知识点,总结一下 1. Flexbox 布局 display: flex;&#xff1a;启用 Flexbox 布局&#xff0c;用于创建灵活的容器。flex-direction: column;&#xff1a;将子元素垂直排列。justify-content&#xff1a;控制子元素在主轴…

双指针算法专题之——复写零

文章目录 题目介绍思路分析异地复写优化为就地复写 AC代码 题目介绍 链接: 1089. 复写零 思路分析 那么这道题我们依然可以使用双指针算法来解决 异地复写 先不考虑题目的要求&#xff0c;直接就地在原数组上修改&#xff0c;可能不太好想&#xff0c;我们这里可以先在一个…

Python控制语句 ——break和continue

1.以下关于Python循环结构的描述中,错误的是() 。 A、break用来结束当前当次语句,但不跳出当前的循环体。 B、遍历循环中的遍历结构可以是字符串、文件、组合数据类型和range函数等。 C、Python通过for,while等保留字构建循环结构。 D、continue只结束本次循环。 答案:A。在…

搭建阿里云专有网络VPC

目录 一、概述 二、专有网络vpc 2.1 vpc基本信息 2.2 vpc资源管理 2.3 vpc网段管理 三、交换机 四、NAT网关 4.1 绑定弹性公网IP 4.2 NAT网关信息 4.3 绑定的弹性公网IP 4.4 DNAT 4.5 SNAT 五、弹性公网IP 六、访问控制ACL&#xff08;绑定交换机&#xff09; 6…