代码随想录算法训练Day58|LeetCode417-太平洋大西洋水流问题、LeetCode827-最大人工岛

太平洋大西洋水流问题

力扣417-太平洋大西洋水流问题

有一个 m × n 的矩形岛屿,与 太平洋 和 大西洋 相邻。 “太平洋” 处于大陆的左边界和上边界,而 “大西洋” 处于大陆的右边界和下边界。

这个岛被分割成一个由若干方形单元格组成的网格。给定一个 m x n 的整数矩阵 heights , heights[r] [c] 表示坐标 (r, c) 上单元格 高于海平面的高度

岛上雨水较多,如果相邻单元格的高度 小于或等于 当前单元格的高度,雨水可以直接向北、南、东、西流向相邻单元格。水可以从海洋附近的任何单元格流入海洋。

返回网格坐标 result 的 2D 列表 ,其中 result[i] = [ri, ci] 表示雨水从单元格 (ri, ci) 流动既可流向太平洋也可流向大西洋 。

示例 1:

img

  • 输入: heights = [[1,2,2,3,5],[3,2,3,4,4],[2,4,5,3,1],[6,7,1,4,5],[5,1,1,2,4]]
  • 输出: [[0,4],[1,3],[1,4],[2,2],[3,0],[3,1],[4,0]]

示例 2:

  • 输入: heights = [[2,1],[1,2]]
  • 输出: [[0,0],[0,1],[1,0],[1,1]]

解题思路

DFS 通过递归或栈来实现,沿着一个路径尽可能深地搜索,直到到达最远的节点,然后回溯并探索其他路径。在这个问题中,从每个起始点开始,DFS 沿着四个方向探索,直到无法继续前进或达到边界。

class Solution {private final int[][] dir = {{-1, 0}, {0, -1}, {1, 0}, {0, 1}}; // 保存四个方向// 从低向高遍历,注意这里 visited 是引用,即可以改变传入的 pacific 和 atlantic 的值private void dfs(int[][] heights, boolean[][] visited, int x, int y) {if (visited[x][y]) return;//如果当前坐标 (x, y) 已经被访问过,则直接返回,不再进行后续操作。visited[x][y] = true;//只要加入,立刻标记为访问过的节点for (int[] d : dir) { // 向四个方向遍历 8-17int nextx = x + d[0];int nexty = y + d[1];// 超过边界if (nextx < 0 || nextx >= heights.length || nexty < 0 || nexty >= heights[0].length) continue;// 高度不合适,注意这里是从低向高判断if (heights[x][y] > heights[nextx][nexty]) continue;dfs(heights, visited, nextx, nexty);}}public List<List<Integer>> pacificAtlantic(int[][] heights) {List<List<Integer>> result = new ArrayList<>();int n = heights.length;int m = heights[0].length; // 这里不用担心空指针,题目要求说了长宽都大于1// 记录从太平洋边出发,可以遍历的节点boolean[][] pacific = new boolean[n][m];// 记录从大西洋出发,可以遍历的节点boolean[][] atlantic = new boolean[n][m];// 从最上最下行的节点出发,向高处遍历for (int i = 0; i < n; i++) {dfs(heights, pacific, i, 0); // 遍历最左列,接触太平洋 dfs(heights, atlantic, i, m - 1); // 遍历最右列,接触大西洋 }// 从最左最右列的节点出发,向高处遍历for (int j = 0; j < m; j++) {dfs(heights, pacific, 0, j); // 遍历最上行,接触太平洋dfs(heights, atlantic, n - 1, j); // 遍历最下行,接触大西洋}// 找到同时被太平洋和大西洋访问的节点for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {if (pacific[i][j] && atlantic[i][j]) result.add(List.of(i, j));}}return result;}
}

result.add(List.of(i, j)

List.of()
List.of方法允许我们创建一个不可变的List集合,其中包含指定的元素。
List immutableList = List.of(“apple”, “banana”, “orange”);

Map.of()
Map.of方法允许我们创建一个不可变的Map集合,其中包含指定的键值对。
Map<String, Integer> immutableMap = Map.of(“apple”, 1, “banana”, 2, “orange”, 3);

Set.of()
Set.of方法允许我们创建一个不可变的Set集合,其中包含指定的元素。
Set immutableSet = Set.of(“apple”, “banana”, “orange”);

最大人工岛

题目描述

力扣827-最大人工岛

给你一个大小为 n x n 二进制矩阵 grid 。最多 只能将一格 0 变成 1 。

返回执行此操作后,grid 中最大的岛屿面积是多少?

岛屿 由一组上、下、左、右四个方向相连的 1 形成。

示例 1:

  • 输入: grid = [[1, 0], [0, 1]]
  • 输出: 3
  • 解释: 将一格0变成1,最终连通两个小岛得到面积为 3 的岛屿。

示例 2:

  • 输入: grid = [[1, 1], [1, 0]]
  • 输出: 4
  • 解释: 将一格0变成1,岛屿的面积扩大为 4。

示例 3:

  • 输入: grid = [[1, 1], [1, 1]]
  • 输出: 4
  • 解释: 没有0可以让我们变成1,面积依然为 4。

解题思路

其实每次深搜遍历计算最大岛屿面积,我们都做了很多重复的工作。

只要用一次深搜把每个岛屿的面积记录下来就好。

第一步:一次遍历地图,得出各个岛屿的面积,并做编号记录。可以使用map记录,key为岛屿编号,value为岛屿面积 第二步:在遍历地图,遍历0的方格(因为要将0变成1),并统计该1(由0变成的1)周边岛屿面积,将其相邻面积相加在一起,遍历所有 0 之后,就可以得出 选一个0变成1 之后的最大面积。

拿如下地图的岛屿情况来举例: (1为陆地)

img

第一步,则遍历题目,并将岛屿到编号和面积上的统计,过程如图所示:

img

本过程代码如下:

    private int[][] dir = {{0, 1}, {1, 0}, {-1, 0}, {0, -1}}; // 四个方向private void dfs(int[][] grid, boolean[][] visited, int x, int y, int mark) {if (visited[x][y] || grid[x][y] == 0) return; // 终止条件:访问过的节点 或者 遇到海水visited[x][y] = true; // 标记访问过grid[x][y] = mark; // 给陆地标记新标签count++;for (int i = 0; i < 4; i++) {int nextx = x + dir[i][0];int nexty = y + dir[i][1];if (nextx < 0 || nextx >= grid.length || nexty < 0 || nexty >= grid[0].length) continue;  // 越界了,直接跳过dfs(grid, visited, nextx, nexty, mark);}}public int largestIsland(int[][] grid) {int n = grid.length, m = grid[0].length;boolean[][] visited = new boolean[n][m]; // 标记访问过的点Map<Integer, Integer> gridNum = new HashMap<>();int mark = 2; // 记录每个岛屿的编号boolean isAllGrid = true; // 标记是否整个地图都是陆地for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {if (grid[i][j] == 0) isAllGrid = false;if (!visited[i][j] && grid[i][j] == 1) {count = 0;dfs(grid, visited, i, j, mark); // 将与其链接的陆地都标记上 truegridNum.put(mark, count); // 记录每一个岛屿的面积mark++; // 记录下一个岛屿编号}}}}

这个过程时间复杂度 n * n 。可能有录友想:分明是两个for循环下面套这一个dfs,时间复杂度怎么回事 n * n呢?

其实大家可以仔细看一下代码,n * n这个方格地图中,每个节点我们就遍历一次,并不会重复遍历

第二步过程如图所示:

img

也就是遍历每一个0的方格,并统计其相邻岛屿面积,最后取一个最大值。

这个过程的时间复杂度也为 n * n。

所以整个解法的时间复杂度,为 n * n + n * n 也就是 n^2。

当然这里还有一个优化的点,就是 可以不用 visited数组,因为有mark来标记,所以遍历过的grid[i] [j]是不等于1的。

不过为了让各个变量各司其事,代码清晰一些,完整代码还是使用visited数组来标记。

最后,整体代码如下:

class Solution {private int count;private int[][] dir = { { 0, 1 }, { 1, 0 }, { -1, 0 }, { 0, -1 } }; // 四个方向private void dfs(int[][] grid, boolean[][] visited, int x, int y, int mark) {if (visited[x][y] || grid[x][y] == 0)return; // 终止条件:访问过的节点 或者 遇到海水visited[x][y] = true; // 标记访问过grid[x][y] = mark; // 给陆地标记新标签count++;for (int i = 0; i < 4; i++) {int nextx = x + dir[i][0];int nexty = y + dir[i][1];if (nextx < 0 || nextx >= grid.length || nexty < 0 || nexty >= grid[0].length)continue; // 越界了,直接跳过dfs(grid, visited, nextx, nexty, mark);}}public int largestIsland(int[][] grid) {int n = grid.length, m = grid[0].length;boolean[][] visited = new boolean[n][m]; // 标记访问过的点Map<Integer, Integer> gridNum = new HashMap<>();int mark = 2; // 记录每个岛屿的编号boolean isAllGrid = true; // 标记是否整个地图都是陆地for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {if (grid[i][j] == 0)isAllGrid = false;if (!visited[i][j] && grid[i][j] == 1) {count = 0;dfs(grid, visited, i, j, mark); // 将与其链接的陆地都标记上 truegridNum.put(mark, count); // 记录每一个岛屿的面积mark++; // 记录下一个岛屿编号}}}if (isAllGrid)return n * m; // 如果都是陆地,返回全面积// 以下逻辑是根据添加陆地的位置,计算周边岛屿面积之和int result = 0; // 记录最后结果Set<Integer> visitedGrid = new HashSet<>(); // 标记访问过的岛屿for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {int currentCount = 1; // 记录连接之后的岛屿数量visitedGrid.clear(); // 每次使用时,清空if (grid[i][j] == 0) {for (int k = 0; k < 4; k++) {int neari = i + dir[k][0]; // 计算相邻坐标int nearj = j + dir[k][1];if (neari < 0 || neari >= grid.length || nearj < 0 || nearj >= grid[0].length)continue;if (visitedGrid.contains(grid[neari][nearj]))continue; // 添加过的岛屿不要重复添加// 把相邻四面的岛屿数量加起来if (grid[neari][nearj] > 1) {currentCount += gridNum.get(grid[neari][nearj]);visitedGrid.add(grid[neari][nearj]); // 标记该岛屿已经添加过}}}result = Math.max(result, currentCount);}}return result;}
}

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

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

相关文章

【Unity】unity学习扫盲知识点

1、建议检查下SystemInfo的引用。这个是什么 Unity的SystemInfo类提供了一种获取关于当前硬件和操作系统的信息的方法。这包括设备类型&#xff0c;操作系统&#xff0c;处理器&#xff0c;内存&#xff0c;显卡&#xff0c;支持的Unity特性等。使用SystemInfo类非常简单。它的…

Linux 查看磁盘是不是 ssd 的方法

lsblk 命令检查 $ lsblk -d -o name,rota如果 ROTA 值为 1&#xff0c;则磁盘类型为 HDD&#xff0c;如果 ROTA 值为 0&#xff0c;则磁盘类型为 SSD。可以在上面的屏幕截图中看到 sda 的 ROTA 值是 1&#xff0c;表示它是 HDD。 2. 检查磁盘是否旋转 $ cat /sys/block/sda/q…

机器学习之保存与加载

前言 模型的数据需要存储和加载&#xff0c;这节介绍存储和加载的方式方法。 存和加载模型权重 保存模型使用save_checkpoint接口&#xff0c;传入网络和指定的保存路径&#xff0c;要加载模型权重&#xff0c;需要先创建相同模型的实例&#xff0c;然后使用load_checkpoint…

Autosar Dcm配置-0x85服务配置及使用-基于ETAS软件

文章目录 前言Dcm配置DcmDsdDcmDsp代码实现总结前言 0x85服务用来控制DTC设置的开启和关闭。某OEM3.0架构强制支持0x85服务,本文介绍ETAS工具中的配置 Dcm配置 DcmDsd 配置0x85服务 此处配置只在扩展会话下支持(具体需要根据需求决定),两个子服务Disable为0x02,Enable…

冯诺依曼体系结构与操作系统(Linux)

文章目录 前言冯诺依曼体系结构&#xff08;硬件&#xff09;操作系统&#xff08;软件&#xff09;总结 前言 冯诺依曼体系结构&#xff08;硬件&#xff09; 上图就是冯诺依曼体系结构图&#xff0c;主要包括输入设备&#xff0c;输出设备&#xff0c;存储器&#xff0c;运算…

Go高级库存照片源码v5.3

GoStock – 免费和付费库存照片脚本这是一个免费和付费共享高质量库存照片的平台,用户可以上传照片与整个社区和访客分享,并可以通过 PayPal 接收捐款。此外,用户还可以点赞、评论、分享和收藏您最喜欢的照片。 下载 特征: 使用Laravel 10构建订阅系统Stripe 连接渐进式网页…

从零开始读RocketMq源码(一)生产者启动

目录 前言 获取源码 总概论 生产者实例 源码 A-01:设置生产者组名称 A-02:生产者服务启动 B-01&#xff1a;初始化状态 B-02&#xff1a;该方法再次对生产者组名称进行校验 B-03&#xff1a;判断是否为默认生产者组名称 B-04: 该方法是为了实例化MQClientInstance对…

白嫖A100-interLM大模型部署试用活动,亲测有效-2.Git

申明 以下部分内容来源于活动教学文档&#xff1a; Docs git 安装 是一个开源的分布式版本控制系统&#xff0c;被广泛用于软件协同开发。程序员的必备基础工具。 常用的 Git 操作 git init 初始化一个新的 Git 仓库&#xff0c;在当前目录创建一个 .git 隐藏文件夹来跟踪…

Windows系统下载安装ngnix

一 nginx下载安装 nginx是HTTP服务器和反向代理服务器&#xff0c;功能非常丰富&#xff0c;在nginx官网首页&#xff0c;点击download 在download页面下&#xff0c;可以选择Stable version稳定版本&#xff0c;点击下载 将下载完成的zip解压即可&#xff0c;然乎在nginx所在…

SpringBoot新手快速入门系列教程五:基于JPA的一个Mysql简单读写例子

现在我们来做一个简单的读写Mysql的项目 1&#xff0c;先新建一个项目&#xff0c;我们叫它“HelloJPA”并且添加依赖 2&#xff0c;引入以下依赖&#xff1a; Spring Boot DevTools (可选&#xff0c;但推荐&#xff0c;用于开发时热部署)Lombok&#xff08;可选&#xff0c…

三相感应电机的建模仿真(2)基于ABC相坐标系S-Fun的仿真模型

1. 概述 2. 三相感应电动机状态方程式 3. 基于S-Function的仿真模型建立 4. 瞬态分析实例 5. 总结 6. 参考文献 1. 概述 前面建立的三相感应电机在ABC相坐标系下的数学模型是一组周期性变系数微分方程&#xff08;其电感矩阵是转子位置角的函数&#xff0c;转子位置角随时…

qt 开发笔记堆栈布局的应用

1.概要 画面中有一处位置&#xff0c;有个按钮点击后&#xff0c;这片位置完全换成另一个画面&#xff0c;这中情况特别适合用堆栈布局。 //堆栈布局的应用 #include <QStackedLayout> QStackedLayout *layout new QStackedLayout(this); layout->setCurrentIndex(…

Unity Scrollview的Scrollbar控制方法

备忘&#xff1a;碰到用scrollview自带的scrollbar去控制滑动&#xff0c;结果发现用代码控制scrollbar.value无效&#xff0c;搜了一下都是说用scrollRect.verticalNormalizedPosition和scrollRect.horizontalNormalizedPosition来控制的。我寻思着有关联的scrollbar为什么用不…

Interview preparation--Https 工作流程

HTTP 传输的弊端 如上图&#xff0c;Http进行数据传输的时候是明文传输&#xff0c;导致任何人都有可能截获信息&#xff0c;篡改信息如果此时黑客冒充服务器&#xff0c;或者黑客窃取信息&#xff0c;则其可以返回任意信息给客户端&#xff0c;而且不被客户端察觉&#xff0c;…

2.3.2 主程序和外部IO交互 (文件映射方式)----C#调用范例

2.3.2 主程序和外部IO交互 &#xff08;文件映射方式&#xff09;----C#调用范例 效果显示 1 说明 1 .1 Test_IOServer是64bit 程序&#xff0c; BD_SharedIOServerd.dll 在 /Debug文件夹中 1 .2 Test_IOServer是32bit 程序&#xff0c; BD_SharedIOClientd.dll (32bit&#…

[FreeRTOS 内部实现] 事件组

文章目录 事件组结构体创建事件组事件组等待位事件组设置位 事件组结构体 // 路径&#xff1a;Source/event_groups.c typedef struct xEventGroupDefinition {EventBits_t uxEventBits;List_t xTasksWaitingForBits; } EventGroup_t;uxEventBits 中的每一位表示某个事件是否…

适用于Mac和Windows的最佳iPhone恢复软件

本文将指导您选择一款出色的iPhone数据恢复软件来检索您的宝贵数据。 市场上有许多所谓的iPhone恢复程序。各种程序很难选择并选择其中之一。一旦您做出了错误的选择&#xff0c;您的数据就会有风险。 最好的iPhone数据恢复软件应包含以下功能。 1.安全可靠。 2.恢复成功率高…

Windows下Visual Studio 中配置第一个CUDA工程

今天整NVIDIA 的CUDA 安装和第一个CUDA 代码&#xff0c;顺便添加一个有CUDA工程的空框架。 &#xff08;1&#xff09;首先确认自己的CUDA 已经安装成功 >>cmd 进入命令窗&#xff0c;在窗口输入查看cuda 是否安装成功&#xff0c;能查到CUDA的版本号&#xff0c;表示安…

基于python的数据分解-趋势-季节性-波动变化

系列文章目录 前言 时间序列数据的分解&#xff0c;一般分为趋势项&#xff0c;季节变化项和随机波动项。可以基于加法或者乘法模型。季节变化呈现出周期变化&#xff0c;因此也叫季节效应(周期&#xff09;。 一、数据分解步骤 &#xff08;1&#xff09;估计时间序列的长期…

仪器校准后出了校准证书后,是不是就代表仪器合格了?

仪器校准是一门技术活&#xff0c;对于从事生产制造的企业而言&#xff0c;是不可或缺的一环&#xff0c;因为这与产品质量密切相关。所以&#xff0c;了解仪器校准的相关知识也变得尤为重要。 在拿到校准证书后&#xff0c;是不是说明仪器合格了&#xff1f;相信不少企业品管人…