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;想考研的技术人儿~别再犹豫了。小编咨询了一大波上岸的大佬&#xff…

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

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

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种 差值就诶够 …

七天学会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; 文章图文…

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

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

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

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

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

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

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

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

Redis 篇

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

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

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

Vivado XADC IP核 使用详解

本文介绍Vivado中XADC Wizard V3.3的使用方法。 XADC简介 XADC Wizard Basic Interface Options&#xff1a; 一共三种&#xff0c;分别是AXI4Lite、DRP、None。勾选后可在界面左侧看到相应通信接口情况。Startup Channel Selection Simultaneous Selection&#xff1a;同时监…

长胜证券:煤价突破900元大关 GLP-1减重药进入集中获批期

上星期五&#xff0c;两市股指早盘震动上扬&#xff0c;午后回落走低。到收盘&#xff0c;沪指跌0.28%报3117.74点&#xff0c;深成指跌0.52%报10144.59点&#xff0c;创业板指涨跌0.45%报2002.73点&#xff0c;科创50指数涨0.71%&#xff1b;两市合计成交7217亿元&#xff0c;…

【算法训练-二叉树 一】【遍历二叉树】前序遍历、中序遍历、后续遍历、层序遍历、锯齿形层序遍历、二叉树右视图

废话不多说&#xff0c;喊一句号子鼓励自己&#xff1a;程序员永不失业&#xff0c;程序员走向架构&#xff01;本篇Blog的主题是【二叉树的遍历】&#xff0c;使用【二叉树】这个基本的数据结构来实现&#xff0c;这个高频题的站点是&#xff1a;CodeTop&#xff0c;筛选条件为…

OmniShade - Mobile Optimized Shader

OmniShade Pro是一款专为移动设备设计的高性能着色器。它包含多种技术,使其几乎可以实现从现实到卡通到动漫的任何外观,但由于自适应系统仅计算任何功能集所需的内容,它的速度也非常快。 它旨在弥合Unity的标准着色器和移动着色器之间的差距,但由于其高级别的风格化、组合…

浏览器事件机制详解

目录 前言 事件类型 鼠标事件 表单事件 窗口事件 DOM事件 多媒体事件 拖拽与放置事件 移动设备事件 剪切板事件 错误事件 过渡、动画事件 事件监听 onevent addEventListener(event) 事件触发 事件流程 捕获阶段 目标阶段 冒泡阶段 事件对象 总结 相关代…

Pyhton压缩JS代码

文章目录 1.安装依赖2.目录结构3.代码4.执行结果 1.安装依赖 pip install jsmin2.目录结构 3.代码 import jsmindef run(src_path, tgt_path):with open(src_path, "r", encodingutf-8) as input_file:with open(tgt_path, "w", encodingutf-8) as outpu…

【Java 基础篇】Java 字节流详解:从入门到精通

Java中的字节流是处理二进制数据的关键工具之一。无论是文件操作、网络通信还是数据处理&#xff0c;字节流都发挥着重要作用。本文将从基础概念开始&#xff0c;深入探讨Java字节流的使用&#xff0c;旨在帮助初学者理解和掌握这一重要主题。 什么是字节流&#xff1f; 在Ja…

Claude 使用指南 | 可与GPT-4媲美的语言模型

本文全程干货&#xff0c;让你轻松使用上claude&#xff0c;这也是目前体验cluade的唯一途径&#xff01;废话不多说&#xff0c;直接上教程&#xff0c;cluade的能力不逊于GPT4&#xff0c;号称是ChatGPT4.0最强竞品。相对Chatgpt来说&#xff0c;Claude不仅是完全免费的&…