LeetCode 热题 100 | 图论(上)

目录

1  200. 岛屿数量

2  994. 腐烂的橘子

2.1  智障遍历法

2.2  仿层序遍历法


菜鸟做题,语言是 C++

1  200. 岛屿数量

解题思路:

  1. 遍历二维数组,寻找 “1”(若找到则岛屿数量 +1)
  2. 寻找与当前 “1” 直接或间接连接在一起的 “1”
  3. 将这些 “1” 置为 “0”,再寻找下一个 “1”

思路说明图:

如步骤 1 所示,我们找到 “1”(红框内部),它可以作为一个岛屿的开头。接下来,我们寻找与这个 “1” 直接或间接连接在一起的 “1”,如步骤 2 所示。这一坨 “1”(红框内部)构成一个岛屿。

直接连接 是指上下左右四个方向,斜对角方向的不算。

除此之外,为了避免我们下一次寻找 “1” 时,把这座岛屿内部的 “1” 视为下一个岛屿的开头,我们要将这些 “1” 置为 “0” 。

我们是对整个二维数组进行遍历的,若不在遍历完一座岛屿后将 “1” 置为 “0”,那么这座岛屿除开头之外的 “1” 会被误认为是下一座岛屿的开头。

具体代码:

① Find “1”:在二维数组中寻找 “1”,作为岛屿的开头。

for (int i = 0; i < nr; ++i) {for (int j = 0; j < nc; ++j) {if (grid[i][j] == '1') {++count;helper(grid, i, j);}}
}

nr 是二维数组的行数,nc 是二维数组的列数。一旦找到 “1” 就 ++count,即认为找到了一座新的岛屿。同时,使用 helper 函数去寻找与当前 “1” 直接或间接连接在一起的 “1” 。

② Find Island:寻找与当前 “1” 直接或间接连接在一起的 “1”,它们构成一座岛屿。

void helper(vector<vector<char>>& grid, int r, int c) {int nr = grid.size();int nc = grid[0].size();grid[r][c] = '0';if (r - 1 >= 0 && grid[r - 1][c] == '1') helper(grid, r - 1, c);if (r + 1 < nr && grid[r + 1][c] == '1') helper(grid, r + 1, c);if (c - 1 >= 0 && grid[r][c - 1] == '1') helper(grid, r, c - 1);if (c + 1 < nc && grid[r][c + 1] == '1') helper(grid, r, c + 1);
}

这四个 if 其实就是做上下左右四个方向的边界判断,同时判断当前 “1” 的邻居是不是 “1” 。若找到相邻的 “1”,那么再递归寻找与相邻的 “1” 直接或间接连接在一起的 “1” 。

class Solution {
public:void helper(vector<vector<char>>& grid, int r, int c) {int nr = grid.size();int nc = grid[0].size();grid[r][c] = '0';if (r - 1 >= 0 && grid[r - 1][c] == '1') helper(grid, r - 1, c);if (r + 1 < nr && grid[r + 1][c] == '1') helper(grid, r + 1, c);if (c - 1 >= 0 && grid[r][c - 1] == '1') helper(grid, r, c - 1);if (c + 1 < nc && grid[r][c + 1] == '1') helper(grid, r, c + 1);}int numIslands(vector<vector<char>>& grid) {int nr = grid.size();if (nr == 0) return 0;int nc = grid[0].size();int count = 0;for (int i = 0; i < nr; ++i) {for (int j = 0; j < nc; ++j) {if (grid[i][j] == '1') {++count;helper(grid, i, j);}}}return count;}
};

2  994. 腐烂的橘子

与  200. 岛屿数量  像又不像,区别在于是否有时间观念

2.1  智障遍历法

解题思路:

  1. 每个时刻都遍历二维数组,寻找腐烂的橘子(2)
  2. 对位于腐烂的橘子(2)四周的新鲜橘子(1)进行污染
  3. 直到所有新鲜橘子都被污染,或者无法继续污染

具体代码:

① 寻找腐烂的橘子(2),与 200 题的代码几乎一样。

for (int i = 0; i < nr; ++i) {for (int j = 0; j < nc; ++j) {if (temp[i][j] == 2)helper(grid, i, j);}
}

② 对位于腐烂的橘子(2)四周的新鲜橘子(1)进行污染。

void helper(vector<vector<int>>& grid, int r, int c) {if (r - 1 >= 0 && grid[r - 1][c] == 1) grid[r - 1][c] = 2;if (r + 1 < nr && grid[r + 1][c] == 1) grid[r + 1][c] = 2;if (c - 1 >= 0 && grid[r][c - 1] == 1) grid[r][c - 1] = 2;if (c + 1 < nc && grid[r][c + 1] == 1) grid[r][c + 1] = 2;
}

③ 判断是否所有的新鲜橘子(1)都被污染。

bool isRotted(vector<vector<int>>& grid) {for (int i = 0; i < nr; ++i) {for (int j = 0; j < nc; ++j) {if (grid[i][j] == 1) return false;}}return true;
}

④ 判断是否无法继续污染:在进行新一轮污染之前,先把上一轮的污染结果 grid 存入 temp 中,如果这一轮污染后有 temp == grid,则说明已经无法继续污染了。

vector<vector<int>> temp = grid;
for (int i = 0; i < nr; ++i) {for (int j = 0; j < nc; ++j) {if (temp[i][j] == 2)helper(grid, i, j);}
}
if (temp == grid) return -1;

这样做还有一个好处,就是可以通过 if (temp[i][j] == 2) 来寻找腐烂的橘子,避免在这一轮中新腐烂的橘子参与到污染中。

class Solution {
public:int nr, nc;void helper(vector<vector<int>>& grid, int r, int c) {if (r - 1 >= 0 && grid[r - 1][c] == 1) grid[r - 1][c] = 2;if (r + 1 < nr && grid[r + 1][c] == 1) grid[r + 1][c] = 2;if (c - 1 >= 0 && grid[r][c - 1] == 1) grid[r][c - 1] = 2;if (c + 1 < nc && grid[r][c + 1] == 1) grid[r][c + 1] = 2;}bool isRotted(vector<vector<int>>& grid) {for (int i = 0; i < nr; ++i) {for (int j = 0; j < nc; ++j) {if (grid[i][j] == 1) return false;}}return true;}int orangesRotting(vector<vector<int>>& grid) {nr = grid.size();nc = grid[0].size();int count = 0;while (!isRotted(grid)) {vector<vector<int>> temp = grid;for (int i = 0; i < nr; ++i) {for (int j = 0; j < nc; ++j) {if (temp[i][j] == 2)helper(grid, i, j);}}if (temp == grid) return -1;++count;if (isRotted(grid)) return count;}return count;}
};

2.2  仿层序遍历法

参考官方题解进行了升级,仿二叉树的层序遍历,不用像 2.1 那样每次都进行全部遍历

核心思想:将属于同一时刻的腐烂橘子视为属于同一层。

上图画出了橘子逐步腐烂的 5 个时刻,每个时刻中打红叉的腐烂橘子属于同一层,打灰叉的腐烂橘子属于上一层。

解题思路:

  • 将属于同一时刻的腐烂橘子送入队列中
  • 出队并遍历属于同一时刻的腐烂橘子
  • 对四周的新鲜橘子进行污染并送入队列中

思路说明图:

对于时刻 1,让腐烂的橘子入队;对于时刻 2,队列中的腐烂橘子出队,让它们对四周的新鲜橘子进行污染,最后将新被污染的橘子入队。以此类推。

在一轮污染中,如果有橘子被污染,则计时器 +1,同时判断新鲜橘子是否被污染完毕;如果没有橘子被污染,则跳出循环,同时判断新鲜橘子是否被污染完毕。若没有橘子被污染且新鲜橘子没有被污染完毕,则表明无法污染所有新鲜橘子。

具体代码:

① 初始化:

  • 计数新鲜橘子的数量,即 freshCount + 1
  • 记录腐烂橘子的位置,即将横纵坐标送入队列中
int freshCount = 0;
queue<pair<int, int>> q;
for (int i = 0; i < nr; ++i) {for (int j = 0; j < nc; ++j) {if (grid[i][j] == 1) {++freshCount;} else if (grid[i][j] == 2) {q.push(make_pair(i, j));}}
}

nr 是 grid 的行数,nc 是 grid 的列数。

② 循环结构和二叉树的层序遍历一模一样:

  • 获取当前层中腐烂橘子的个数
  • 遍历当前层中的腐烂橘子
while (!q.empty()) {int currentSize = q.size();for (int i = 0; i < currentSize; ++i) {pair<int, int> pos = q.front();q.pop();// 对橘子进行污染}
}

③ 针对每个腐烂橘子,对其四周进行污染:

  • 判断上/下/左/右位置是否越界,若越界则跳过该位置
  • 若该位置上的是新鲜橘子,则进行污染并将其入队
  • 同时将污染标志置为 true,新鲜橘子数量 - 1
for (int i = 0; i < 4; ++i) {int x = pos.first + dir_x[i];int y = pos.second + dir_y[i];if (x < 0|| x >= nr || y < 0|| y >= nc || grid[x][y] == 0)continue;if (grid[x][y] == 1) {hasPolluted = true;--freshCount;grid[x][y] = 2;q.push(make_pair(x, y));}if (freshCount == 0) break;
}

hasPolluted 用于表明当前层中是否至少有一个腐烂橘子造成了污染,如果没有造成污染,那么就要考虑是否无法污染所有新鲜橘子了。

class Solution {
public:int dir_x[4] = {0, 1, 0, -1};int dir_y[4] = {1, 0, -1, 0};int orangesRotting(vector<vector<int>>& grid) {int nr = grid.size();if (nr == 0) return 0;int nc = grid[0].size();int freshCount = 0;queue<pair<int, int>> q;for (int i = 0; i < nr; ++i) {for (int j = 0; j < nc; ++j) {if (grid[i][j] == 1) {++freshCount;} else if (grid[i][j] == 2) {q.push(make_pair(i, j));}}}int timeCount = 0;int hasPolluted = false;while (!q.empty()) {int currentSize = q.size();for (int i = 0; i < currentSize; ++i) {pair<int, int> pos = q.front();q.pop();for (int i = 0; i < 4; ++i) {int x = pos.first + dir_x[i];int y = pos.second + dir_y[i];if (x < 0|| x >= nr || y < 0|| y >= nc || grid[x][y] == 0)continue;if (grid[x][y] == 1) {hasPolluted = true;--freshCount;grid[x][y] = 2;q.push(make_pair(x, y));}if (freshCount == 0) break;}}if (hasPolluted) ++timeCount;hasPolluted = false;}return freshCount == 0 ? timeCount : -1;}
};

技能点:使用循环结构来测试上/下/左/右四个方位。

int dir_x[4] = {0, 1, 0, -1};
int dir_y[4] = {1, 0, -1, 0};for (int i = 0; i < 4; ++i) {int x = pos.first + dir_x[i];int y = pos.second + dir_y[i];if (x < 0|| x >= nr || y < 0|| y >= nc)// ...
}

并且用逆否命题来作为判断条件,就不需要写很多 && 了!

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

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

相关文章

项目登录方案选型

一.Cookie + Session 登录 大家都知道,HTTP 是一种无状态的协议。无状态是指协议对于事务处理没有记忆能力,服务器不知道客户端是什么状态。即我们给服务器发送 HTTP 请求之后,服务器根据请求返回数据,但不会记录任何信息。为了解决 HTTP 无状态的问题,出现了 Cookie。Co…

离线数仓(四)【数仓数据同步策略】

前言 今天来把数仓数据同步解决掉&#xff0c;前面我们已经把日志数据到 Kafka 的通道打通了。 1、实时数仓数据同步 关于实时数仓&#xff0c;我们的 Flink 直接去 Kafka 读取即可&#xff0c;我们在学习 Flink 的时候也知道 Flink 提供了 Kafka Source&#xff0c;所以这里不…

协议-http协议-基础概念02-请求应答过程-请求响应报文结构-头部字段-请求方法-响应方式

参考来源&#xff1a; 极客时间-透视HTTP协议(作者&#xff1a;罗剑锋)&#xff1b; web抓包实战课-陶辉&#xff1b; 01-HTTP协议请求-应答过程 最简单的浏览器 HTTP 请求过程 浏览器从地址栏的输入中获得服务器的 IP 地址和端口号&#xff1b;浏览器用 TCP 的三次握手与服…

基于springboot的4S店车辆管理系统源码和论文

随着信息技术和网络技术的飞速发展&#xff0c;人类已进入全新信息化时代&#xff0c;传统管理技术已无法高效&#xff0c;便捷地管理信息。为了迎合时代需求&#xff0c;优化管理效率&#xff0c;各种各样的管理系统应运而生&#xff0c;各行各业相继进入信息管理时代&#xf…

win10开机黑屏,只有鼠标,解决方案

问题描述 win10进不去桌面&#xff0c;可以进去锁屏&#xff0c;只有鼠标&#xff0c;也能进去任务管理器&#xff08;ctrlwindelete&#xff09;, 问题分析 进入任务管理器->文件->运行新任务 然后输入 explorer.exe 发现找不到了 原因&#xff1a;误删explorer.exe …

Linux系统---nginx(1)服务

目录 一.Nginx概述 1.定义 2.Nginx模块作用 &#xff08;1&#xff09;main模块 &#xff08;2&#xff09;stream服务模块 &#xff08;3&#xff09;邮件服务模块 &#xff08;4&#xff09;第三方模块 &#xff08;5&#xff09;events模块 &#xff08;6&#xff0…

300分钟吃透分布式缓存-16讲:常用的缓存组件Redis是如何运行的?

Redis 基本原理 Redis 简介 Redis 是一款基于 ANSI C 语言编写的&#xff0c;BSD 许可的&#xff0c;日志型 key-value 存储组件&#xff0c;它的所有数据结构都存在内存中&#xff0c;可以用作缓存、数据库和消息中间件。 Redis 是 Remote dictionary server 即远程字典服务…

SpringCloud有哪些组件

什么是SpringCloud&#xff1f; Spring Cloud是基于Spring Boot的分布式系统开发工具&#xff0c;它提供了一系列开箱即用的、针对分布式系统开发的特性和组件&#xff0c;用于帮助开发人员快速构建和管理云原生应用程序。 Spring Cloud的主要目标是解决分布式系统中的常见问题…

代码随想录算法训练营第二十七天补|39. 组合总和 ● 40.组合总和II ● 131.分割回文串

组合问题&#xff1a;集合内元素的组合&#xff0c;不同集合内元素的组合 分割问题&#xff1a;本质还是组合问题&#xff0c;注意一下如何分割字符串 回溯模板伪代码 void backtracking(参数) {if (终止条件) {存放结果;return;}for (选择&#xff1a;本层集合中元素&#xf…

【Maven】Maven 基础教程(一):基础介绍、开发环境配置

Maven 基础教程&#xff08;一&#xff09;&#xff1a;基础介绍、开发环境配置 1.Maven 是什么1.1 构建1.2 依赖 2.Maven 开发环境配置2.1 下载安装2.2 指定本地仓库2.3 配置阿里云提供的镜像仓库2.4 配置基础 JDK 版本2.5 配置环境变量 1.Maven 是什么 Maven 是 Apache 软件…

N个数中寻找前K个最大的数

文章目录 一、先把这N个数的前K个建立一个小堆二、再把这K个数与剩下的N-K个数进行比较交换三、最后用向下调整算法就可以得到这N个数中最大的前K个 一、先把这N个数的前K个建立一个小堆 先创建一个文本文件&#xff0c;然后向里面写数据&#xff0c;这里N我设置的是1000 int n…

【web APIs】1、(学习笔记)有案例!

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、概念二、使用步骤1.获取DOM对象2.操作元素内容3.属性修改3.1.常用属性修改3.2.控制样式属性3.3.操作类名(className) 操作CSS3.4.操作表单元素属性3.5.自定…

【LeetCode每日一题】938. 二叉搜索树的范围和

2024-2-26 文章目录 [938. 二叉搜索树的范围和](https://leetcode.cn/problems/range-sum-of-bst/)思路&#xff1a;写法一&#xff1a;在中间累加写法二&#xff1a;在最后累加 938. 二叉搜索树的范围和 思路&#xff1a; 1.在二叉搜索树中&#xff1a;左子树的结点都小于根节…

小甲鱼Python06 序列字典集合

一、序列 1.id函数 is运算符 我们首先思考下字符串、元组、列表的共同点&#xff1a; 都有很多共同的运算符。都可以通过索引来获取元素&#xff0c;第一个元素索引都是0&#xff0c;都可以通过切片的方法获取某个范围内元素的集合。 以上三种统称为序列。序列分为可变序列…

抖音视频评论采集软件|抖音数据抓取工具

抖音视频评论采集软件是一款基于C#开发的高效、便捷的工具&#xff0c;旨在为用户提供全面的数据采集和分析服务。该软件不仅支持通过关键词进行搜索抓取&#xff0c;还能够通过分享链接进行单个视频的抓取和下载&#xff0c;让用户轻松获取抖音视频评论数据。 其中&#xff0c…

JSP实现数据传递与保存(一)

一、Web开发步骤 1.1两类模式 后端——————前端 先有前端&#xff0c;前端用的时候直接调用 后端已实现注册接口&#xff0c;接口名为doRegister.jsp 前端此时&#xff1a; 前端的form表单中的action提交地址就只能填doRegister.jsp&#xff0c;即&#xff1a; <f…

10.网络游戏逆向分析与漏洞攻防-游戏网络架构逆向分析-接管游戏发送数据的操作

内容参考于&#xff1a;易道云信息技术研究院VIP课 上一个内容&#xff1a;接管游戏连接服务器的操作 码云地址&#xff08;master 分支&#xff09;&#xff1a;染指/titan 码云版本号&#xff1a;00820853d5492fa7b6e32407d46b5f9c01930ec6 代码下载地址&#xff0c;在 ti…

Doris——荔枝微课统一实时数仓建设实践

目录 一、业务介绍 二、早期架构及痛点 2.1 早期架构 2.2 架构痛点 三、技术选型 四、新的架构及方案 五、搭建经验 5.1 数据建模 5.2 数据开发 5.3 库表设计 5.4 数据管理 5.4.1 监控告警 5.4.2 数据备份与恢复 六、收益总结 七、未来规划 原文大佬这篇Doris腾…

适配器模式(Adapter Pattern) C++

上一节&#xff1a;原型模式&#xff08;Prototype Pattern&#xff09; C 文章目录 0.理论1.组件2.类型3.什么时候使用 1.实践1.基础接口和类2.类适配器实现3.对象适配器实现 0.理论 适配器模式&#xff08;Adapter Pattern&#xff09;是一种结构型设计模式&#xff0c;它允…

日更【系统架构设计师知识总结3】存储系统

【原创精华总结】自己一点点手打、总结的脑图&#xff0c;把散落在课本以及老师讲授的知识点合并汇总&#xff0c;反复提炼语言&#xff0c;形成知识框架。希望能给同样在学习的伙伴一点帮助&#xff01;