Day66|图part5:130. 被围绕的区域、827.最大人工岛

130. 被围绕的区域

leetcode链接:题目链接

image

这题看起来很复杂,其实跟之前找飞地和找边缘地区的是差不多的,主要分三步:

  • 使用dfs将边缘的岛都找出来,然后用A代替防止混淆;
  • 再用dfs找中间不与任何岛相连的飞地;
  • 最后把之前的A替换成O。

最终代码:

class Solution {
public:void dfs(vector<vector<char>> &board, int i, int j, char ch){//找到o把其周围转化为chvector<int> dir = {0,-1,0,1,1,0,-1,0};if(i < 0 || j < 0 || i >= board.size() || j >= board[0].size()){return;}if(board[i][j] == 'X' || board[i][j] == 'a'){return;}board[i][j] = ch;for(int idx = 0; idx < 4; idx++){dfs(board, i + dir[2 * idx], j + dir[2 * idx + 1],ch);}}void solve(vector<vector<char>>& board) {int m = board.size();int n = board[0].size();for(int i = 0; i < m; i++){if(board[i][n - 1] == 'O'){dfs(board,i, n - 1, 'a');}if(board[i][0] == 'O'){dfs(board,i,0, 'a');}}for(int j = 0; j < n; j++){if(board[0][j] == 'O'){dfs(board,0, j,'a');}if(board[m - 1][j] == 'O'){dfs(board, m - 1, j,'a');}}for(int i = 0; i < m; i++){for(int j = 0; j < n;j++){if(board[i][j] == 'O'){board[i][j] = 'X';}if(board[i][j] =='a'){board[i][j] = 'O';}}}
//        for(int i = 0; i < m; i++){
//            for(int j = 0; j < n;j++){
//                if(board[i][j] =='a'){
//                    board[i][j] = 'O';
//                }
//            }
//        }}
};

这里有几点注意的:

  • dfs函数中,除了等于X需要return,等于A也需要return,否则递归就没办法结束。
  • 只需要dfs淹没周围一圈的岛,中间的岛不用再dfs找了,直接替换就行,因为本题没有让我们以整个岛为单位做一些事情。

417. 太平洋大西洋水流问题

leetcode链接:题目链接

image

image

输入: 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]]

首先这题题目我都没怎么看懂,理解一下题意。

输入是一个二维数组,只要位于该点的值比四个方向的高就可以流向其他方向,最终既可以流向右边、下边(大西洋),又可以流向左边、上边(太平洋)的符合结果,输出result。

首先能想到一个很朴素的思路就是,对每个点都判断一下是否能同时流向大西洋和太平洋。这种思路的实现代码如下:

class Solution {
private:int dir[4][2] = {-1, 0, 0, -1, 1, 0, 0, 1};void dfs(vector<vector<int>>& heights, vector<vector<bool>>& visited, int x, int y) {if (visited[x][y]) return;visited[x][y] = true;for (int i = 0; i < 4; i++) {int nextx = x + dir[i][0];int nexty = y + dir[i][1];if (nextx < 0 || nextx >= heights.size() || nexty < 0 || nexty >= heights[0].size()) continue;if (heights[x][y] < heights[nextx][nexty]) continue; // 高度不合适dfs (heights, visited, nextx, nexty);}return;}bool isResult(vector<vector<int>>& heights, int x, int y) {vector<vector<bool>> visited = vector<vector<bool>>(heights.size(), vector<bool>(heights[0].size(), false));// 深搜,将x,y出发 能到的节点都标记上。 dfs(heights, visited, x, y);bool isPacific = false;bool isAtlantic = false;// 以下就是判断x,y出发,是否到达太平洋和大西洋 for (int j = 0; j < heights[0].size(); j++) {if (visited[0][j]) {isPacific = true;break;}}for (int i = 0; i < heights.size(); i++) {if (visited[i][0]) {isPacific = true;break;}}for (int j = 0; j < heights[0].size(); j++) {if (visited[heights.size() - 1][j]) {isAtlantic = true;break;}}for (int i = 0; i < heights.size(); i++) {if (visited[i][heights[0].size() - 1]) {isAtlantic = true;break;}}if (isAtlantic && isPacific) return true;return false;}
public:vector<vector<int>> pacificAtlantic(vector<vector<int>>& heights) {vector<vector<int>> result;// 遍历每一个点,看是否能同时到达太平洋和大西洋 for (int i = 0; i < heights.size(); i++) {for (int j = 0; j < heights[0].size(); j++) {if (isResult(heights, i, j)) result.push_back({i, j});}}return result;}
};

这种思路很直白,但很明显,以上代码超时了。 来看看时间复杂度。

遍历每一个节点,是 m * n,遍历每一个节点的时候,都要做深搜,深搜的时间复杂度是: m * n

那么整体时间复杂度 就是 O(m^2 * n^2) ,这是一个四次方的时间复杂度。

优化

那么我们可以 反过来想,从太平洋边上的节点 逆流而上,将遍历过的节点都标记上。 从大西洋的边上节点 逆流而长,将遍历过的节点也标记上。 然后两方都标记过的节点就是既可以流太平洋也可以流大西洋的节点。

class Solution {
private:int dir[4][2] = {-1, 0, 0, -1, 1, 0, 0, 1}; // 保存四个方向// 从低向高遍历,注意这里visited是引用,即可以改变传入的pacific和atlantic的值void dfs(vector<vector<int>>& heights, vector<vector<bool>>& visited, int x, int y) {if (visited[x][y]) return;visited[x][y] = true;for (int i = 0; i < 4; i++) { // 向四个方向遍历int nextx = x + dir[i][0];int nexty = y + dir[i][1];// 超过边界if (nextx < 0 || nextx >= heights.size() || nexty < 0 || nexty >= heights[0].size()) continue;// 高度不合适,注意这里是从低向高判断if (heights[x][y] > heights[nextx][nexty]) continue;dfs (heights, visited, nextx, nexty);}return;}public:
vector<vector<int>> pacificAtlantic(vector<vector<int>>& heights) {vector<vector<int>> result;int n = heights.size();int m = heights[0].size(); // 这里不用担心空指针,题目要求说了长宽都大于1// 记录从太平洋边出发,可以遍历的节点vector<vector<bool>> pacific = vector<vector<bool>>(n, vector<bool>(m, false));// 记录从大西洋出发,可以遍历的节点vector<vector<bool>> atlantic = vector<vector<bool>>(n, vector<bool>(m, false));// 从最上最下行的节点出发,向高处遍历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.push_back({i, j});}}return result;}
};

所以 调用dfs函数,只要参数传入的是 数组pacific,那么地图中 每一个节点其实就遍历一次,无论你调用多少次

同理,调用 dfs函数,只要 参数传入的是 数组atlantic,地图中每个节点也只会遍历一次。

所以,以下这段代码的时间复杂度是 2 * n * m。 地图用每个节点就遍历了两次,参数传入pacific的时候遍历一次,参数传入atlantic的时候遍历一次。

827. 最大人工岛

leetcode链接:力扣链接

给你一个大小为 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

https://www.programmercarl.com/0827.%E6%9C%80%E5%A4%A7%E4%BA%BA%E5%B7%A5%E5%B2%9B.html#%E4%BC%98%E5%8C%96%E6%80%9D%E8%B7%AF

先放这里放一下。题目居然是hard,不太想做岛屿类的题了,换换脑子。

总结

  • 岛屿问题的dfs/bfs的代码基本大差不差,主要还是主函数中处理逻辑的问题;
  • 学习带有 visited的dfs的写法。

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

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

相关文章

工作比读研简单多了

工作比读研简单多了&#xff0c;因为至少有人能解答 工作遇到的问题相比读研时遇到的问题幸福太多&#xff0c;简单太多。因为读研时遇到的更多是未知的问题&#xff0c;是科学问题&#xff0c;是论文中也没有答案的问题&#xff0c;问不着答案&#xff0c;搜不着结果&#xf…

【码银送书第七期】七本考研书籍

八九月的朋友圈刮起了一股晒通知书潮&#xff0c;频频有大佬晒出“研究生入学通知书”&#xff0c;看着让人既羡慕又焦虑。果然应了那句老话——比你优秀的人&#xff0c;还比你努力。 心里痒痒&#xff0c;想考研的技术人儿~别再犹豫了。小编咨询了一大波上岸的大佬&#xff…

UDP与TCP报头介绍,三次握手与四次挥手详谈

先介绍我们UDP/TCP协议缓冲区 在UDP和TCP在数据传输和介绍时有有缓冲区概念的。 UDP缓冲区 UDP没有真正意义上的 发送缓冲区. 调用sendto会直接交给内核, 由内核将数据传给网络层协议进行后 续的传输动作; UDP具有接收缓冲区. 但是这个接收缓冲区不能保证收到的UDP报的顺序…

C++智能指针种类以及使用场景

一、指针管理的困境 资源释放了&#xff0c;指针没有置空 野指针&#xff1a;只有一个指针指向资源 指针悬挂&#xff1a;多个指针指向同一个资源 踩内存 没有释放资源&#xff0c;产生内存泄漏 重复释放资源&#xff0c;引发 coredump 二、如何解决&#xff1f; 智能指针采…

C语言天花板——指针(初阶)

&#x1f320;&#x1f320;&#x1f320; 大家在刚刚接触C语言的时候就肯定听说过&#xff0c;指针的重要性以及难度等级&#xff0c;以至于经常“谈虎色变”&#xff0c;但是今天我来带大家走进指针的奇妙世界。&#x1f387;&#x1f387;&#x1f387; 一、什么是指针&…

旋转角度对迭代次数的影响

( A, B )---3*30*2---( 1, 0 )( 0, 1 ) 让网络的输入只有3个节点&#xff0c;AB训练集各由5张二值化的图片组成&#xff0c;让A中有3个1&#xff0c;B中全是0&#xff0c;统计迭代次数并排序。 在3*5的空间内分布3个点有19种可能&#xff0c;但不同的分布只有6种 差值就诶够 …

CSS 文本超出省略

单行省略 width: 200px; /* 容器宽度 */ white-space: nowrap; /* 不换行 */ overflow: hidden; /* 溢出隐藏 */ text-overflow: ellipsis; /* 超出部分省略 */多行省略 display: -webkit-box; -webkit-line-clamp: 2; /* 限制行数 */ -webkit-box-orient: vertical; /* 文本…

七天学会C语言-第二天(数据结构)

1. If 语句&#xff1a; If 语句是一种条件语句&#xff0c;用于根据条件的真假执行不同的代码块。它的基本形式如下&#xff1a; if (条件) {// 条件为真时执行的代码 } else {// 条件为假时执行的代码 }写一个基础的If语句 #include<stdio.h> int main(){int x 10;…

硬件故障诊断:快速定位问题

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

Vue3+element plus+sortablejs实现table列表拖拽

1、安装 npm install sortablejs --save2、引入 import Sortable from sortablejs;3、使用 表格表头必须加row-key&#xff0c;否则会出现排序错乱完整代码table.vue <el-table v-loading"loading"row-key"id":height"tableHeight"ref&qu…

Linux基础开发工具使用快速上手

软件包管理器 概念理解 在Linux下安装软件的话&#xff0c;一个比较原始的办法是下载程序的源代码&#xff0c;然后进行编译&#xff0c;进而得到可执行程序&#xff0c;然后就可以运行这个软件了。但是这种做法太麻烦了&#xff0c;于是就有些人把一些常用的软件提前编译好&…

Python子进程管理与进程信息获取

1. Python子进程模块subprocess subprocess 模块允许我们启动一个新进程&#xff0c;并连接到它们的输入/输出/错误管道&#xff0c;从而获取返回值。 &#xff08;1&#xff09;run 方法 首先我们来看看 run 方法的使用&#xff0c;该方法的参数如下&#xff1a; args&…

笔记1.5:计算机网络体系结构

从功能上描述计算机网络结构 分层结构 每层遵循某个网络协议完成本层功能 基本概念 实体&#xff1a;表示任何可发送或接收信息的硬件或软件进程。 协议是控制两个对等实体进行通信的规则的集合&#xff0c;协议是水平的。 任一层实体需要使用下层服务&#xff0c;遵循本层…

uniapp 小程序 父组件调用子组件方法

答案&#xff1a;配合小程序API > this.selectComponent("")&#xff0c;来选择组件&#xff0c;再使用$vm选择组件实例&#xff0c;再调用方法&#xff0c;或者data 1 设置组件的id,如果你的多端&#xff0c;请跟据情况设置ref,class,id&#xff0c;以便通过小…

区块链(1):区块链简介

区快链是通过密码技术保护的分布式数据库这是比特币背后的技术。 本文将逐步带您了解区块链。 1 区块链BLOCKCHAIN的类的定义 区块链有一个区块列表。 它从一个单独的块开始&#xff0c;称为 genesis block【创世区块】 2 区块链BLOCK的类的定义 第一个区块叫做 Genesis[…

QT5到QT6产生的一些变化【QT环境搭建篇】

1、QT 重写enterEvent 鼠标进入事件没有作用 widget中的事件函数 由原来的event(QEvent *event) 变为enterEvent(QEnterEvent *event) 重写改成这样就可以了 void enterEvent(QEnterEvent *event); 2、error C4996: QString::SkipEmptyParts&#xff08;“SkipEmptyParts”:…

一阶低通滤波器滞后补偿算法

一阶低通滤波器的推导过程和双线性变换算法请查看下面文章链接: PLC算法系列之数字低通滤波器(离散化方法:双线性变换)_双线性离散化_RXXW_Dor的博客-CSDN博客PLC信号处理系列之一阶低通(RC)滤波器算法_RXXW_Dor的博客-CSDN博客_rc滤波电路的优缺点1、先看看RC滤波的优缺点…

Redis 篇

1、为什么要用缓存&#xff1f; 使用缓存的目的就是提升读写性能。而实际业务场景下&#xff0c;更多的是为了提升读性能&#xff0c;带来更好的性能&#xff0c;带来更高的并发量。 Redis 的读写性能比 Mysql 好的多&#xff0c;我们就可以把 Mysql 中的热点数据缓存到 Redis…

设计模式:组合模式

目录 组件代码实现优缺点源码中应用总结 组合模式是一种结构型设计模式&#xff0c;用于将对象组织成树形结构&#xff0c;以表示“部分-整体”的层次结构。组合模式使得客户端可以统一地处理单个对象和组合对象&#xff0c;而不需要区分它们之间的差异。 在组合模式中&#x…

Linux学习第14天:Linux设备树(一):枝繁叶茂见晴天

本节笔记主要学习了Linux设备树相关知识点&#xff0c;由于内容较多&#xff0c;打算分两天进行总结。今天着重学习Linux设备树&#xff0c;主要包括前三节内容&#xff0c;分别是概念、格式和语法。 本节思维导图内容如下&#xff1a; 一、什么是设备树 设备树可以用一个图来进…