Leetcode热题100:图论

Leetcode 200. 岛屿数量

深度优先搜索法:

对于这道题来说,是一个非常经典的图的问题,我们可以先从宏观上面来看问题,也就是说在不想具体算法的前提下,简单的说出如何找到所有的岛屿呢?

如图中所示,首先非常显而易见的要素就是我们一定要遍历图中的每一个坐标,这是肯定的,然后呢对于岛屿的数量,一开始想的肯定就是每当我们访问了一个1的坐标时,我们就找到了一个岛屿,可是因为我们要遍历整个图,所以肯定不能每次遇到一个1就对岛屿的数量进行增加,因为题目说了,横纵连接着的坐标都是1的话都属于同一个岛屿,就像上图一样证明我们只有三个岛屿

那么我们是不是可以像一个办法,当我们找到了一个岛屿的坐标后,把属于这个坐标的岛屿的其他所有值为1的坐标都记录下来,这样以来,意思就是说在我们继续遍历的时候,我们检查每一个坐标时,如果发现这个坐标已经被标记过了,证明他并不是一个新的岛屿而是一个之前就发现过的岛屿的一部分那么就可以了

如何去实现这个标记的方法呢,就可以用到我们的深度优先搜索,从新发现的坐标开始一直找,直到找到了岛屿的边缘或者整个图的边缘之后返回,这样就能找到所有属于相同岛屿的坐标,那么我们可以把主代码写出来了已经

class Solution:def numIslands(self, grid: List[List[str]]) -> int:res = 0# iterate to check every box in the grid to see# if it is a start for a new lslandfor r in range(len(grid)):for c in range(len(grid[0])):# if so, run a dfs to mark all its fellow# box and add the 1 to the resultif grid[r][c] == '1':dfs(grid, r, c)res = res + 1return res

主体部分的代码非常简单,然后呢我们需要做的就是对于dfs的编写,正如在这个主体代码中写的,你会发现我这里还是用的如果box中存的元素是1,那就最终要增加岛屿数量,这难道不是错的吗?其实这里就隐喻了我们是如何完成对一个岛屿上所有的box进行标记的,与其新建一个空间例如集合然后把dfs中搜索到的box全都加入进去然后每一次循环遍历的时候去看当前的box是否在那个集合中,更好的方法其实就是直接原地更改我们的grid,将搜索到的box中的值从1修改到2,这样这个主体函数中的if 语句就不会被execute了

class Solution:def numIslands(self, grid: List[List[str]]) -> int:def dfs(grid, r, c):# base case, do nothing when we# reached the edge of entire grid or found waterif not (0 <= r < len(grid) and 0 <= c < len(grid[0])) or grid[r][c] != '1':return# mark the visited box as 2grid[r][c] = '2'# call the recursive case on each direction from current boxdfs(grid, r - 1, c)dfs(grid, r + 1, c)dfs(grid, r, c - 1)dfs(grid, r, c + 1)res = 0# iterate to check every box in the grid to see# if it is a start for a new lslandfor r in range(len(grid)):for c in range(len(grid[0])):# if so, run a dfs to mark all its fellow# box and add the 1 to the resultif grid[r][c] == '1':dfs(grid, r, c)res = res + 1return res

这样你就有了整个的代码,其实这种类型的深度优先搜索可以参考我们在二叉树的时候是怎么做的,无非也是一直遍历然后直到我们reach 到了leaf node然后发现新的node是空的时候就直接return,这里不过是多加了两个方向,在二叉树里的recursive case是对左右子节点继续call,这里是对上下左右四个横纵坐标的方向继续call,然后呢条件多加了一个,这里对应的不能超出边界就是二叉树中的if not root, 只是这里还要保证grid[r][c] == 1,不是1的话就不是我们要找的同一个岛屿上的点

时间复杂度 O(m*n):m和n就是grid的长和宽,因为我们要遍历每一个坐标

空间复杂度 O(m*n):在最坏的情况下,如果左上角的box就是陆地1,并且整张图都是1,                                       那么我们就要把每一个box都有一个recursive function,这样在就会用                                     到一个大小为m*n的栈


Leetcode 994. 腐烂的橘子

广度优先搜索法:

这道题的关键在于我们在一开始所给的grid里面存在多个橘子的可能,我们需要在把能弄腐烂的橘子全部弄完之后就返回结果,所以每一分钟里我们需要对所有当前的橘子进行扩散,这里运用深度优先的递归就很麻烦,因为我们每一次逻辑要处理多个搜索

这里我们就使用广度优先,利用队列来对腐烂橘子进行保存并且通过出队来进行遍历然后扩散后把新的腐烂的橘子继续加入队列

这样以来,每一次我们通过向四个方向的检查中发现新的好橘子之后就可以立马对其进行操作,具体分三步,第一步将其加入我们的队列代表下一轮遍历的时候,他会pop出来作为新的坐标然后向四周扩散,第二步将我们的好橘子的count做一个递减,第三步,将grid中其坐标位置的值从1变成2避免后序的遍历中反复visit这个坏橘子

class Solution:def orangesRotting(self, grid: List[List[int]]) -> int:# we are using a queue to do the bfsq = deque()fresh_count = 0res = 0# loop through the gird first to find # the amount of fresh and add the rotten to# the queuefor i in range(len(grid)):for j in range(len(grid[0])):if grid[i][j] == 1:fresh_count = fresh_count + 1elif grid[i][j] == 2:q.append((i, j))# loop until we have no more rotten orangewhile q and fresh_count > 0:# every time we start pop out q again, we did another searchres = res + 1# for each rotten orango, pop them outfor _ in range(len(q)):box = q.popleft()r, c = box[0], box[1]# check topif r - 1 >= 0 and grid[r - 1][c] == 1:fresh_count = fresh_count - 1q.append((r - 1, c))grid[r - 1][c] = 2# check rightif c + 1 < len(grid[0]) and grid[r][c + 1] == 1:fresh_count = fresh_count - 1q.append((r, c + 1))grid[r][c + 1] = 2# check botif r + 1 < len(grid) and grid[r + 1][c] == 1:fresh_count = fresh_count - 1q.append((r + 1, c))      grid[r + 1][c] = 2# check leftif c - 1 >= 0 and grid[r][c - 1] == 1:fresh_count = fresh_count - 1q.append((r, c - 1))grid[r][c - 1] = 2# we did not get them all rottonif fresh_count > 0:return -1else:return res

时间复杂度 O(m*n):m和n就是grid的长和宽,因为我们要遍历每一个坐标

空间复杂度 O(m*n):在最坏的情况下,一开始所有的橘子都是坏橘子,我们使用的额外空间队列的长度最大就是m*n

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

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

相关文章

win git filter-repo教程

git filter-repo 是一个用于过滤和清理 Git 仓库历史的工具&#xff0c;它可以高效地批量修改提交历史中的文件内容、删除文件、重命名文件以及进行其他历史重构操作。相较于 git filter-branch&#xff0c;它通常更快且更易于使用。 以下是一个基本示例&#xff0c;说明如何使…

oracle 19c单机版本补丁升级

文章目录 一、补丁包概述二、备份opatch三、替换高版本opatch四、打DB补丁1、关闭数据库2、关闭监听3、解压补丁4、冲突检测5、补丁空间检查6、执行补丁升级7、将更新内容加载到数据库8、最后查看数据库版本9、卸载补丁包 一、补丁包概述 补丁升级包 链接&#xff1a;https://…

【系统架构设计师】计算机系统基础知识 03

系统架构设计师 - 系列文章目录 01 系统工程与信息系统基础 02 软件架构设计 03 计算机系统基础知识 文章目录 系统架构设计师 - 系列文章目录 文章目录 前言 一、计算机系统概述 1.计算机组成 ​编辑2.存储系统 二、操作系统 ★★★★ 1.进程管理 2.存储管理 1.页式存储 …

Golang Gorm 自动分批查询

场景&#xff1a; 目标查询全量数据&#xff0c;但需要每次Limit分批查询&#xff0c;保护数据库 文档&#xff1a; https://gorm.io/zh_CN/docs/advanced_query.html // Param: // dest 目标地址 // batchSize 大小 // fc 处理函数func (db *DB) FindInBatc…

安卓 Android Activity 生命周期

文章目录 Intro生命周期方法 & 执行顺序结论code Intro 本文提供一个测试类通过打印的方式展示在多个Activity之间互相跳转的时候&#xff0c;各个Activity的生命周期相关方法的执行顺序。 生命周期方法 & 执行顺序结论 下图出自 郭霖 《第一行代码&#xff08;第二…

速盾:免备案cdn的好处

免备案CDN&#xff08;Content Delivery Network&#xff09;是指不需要进行备案手续即可使用的CDN服务。备案是指在中国大陆地区提供互联网信息服务的网站必须向相关部门进行备案登记&#xff0c;以确保其合法合规的运营。 那么&#xff0c;免备案CDN有哪些好处呢&#xff1f…

电网的正序参数和等值电路(一)

本篇为本科课程《电力系统稳分析》的笔记。 本篇为第二章的第一篇笔记。 电力系统正常运行中&#xff0c;可以认为系统的三相结构和三相负荷完全对称。而对称三相的计算可以用一相来完成&#xff0c;其中所有给出的标称电压都是线电压的有效值&#xff0c;假定系统全部是Y-Y型…

深入了解23种设计模式:程序员必读指南

文章目录 引言概述基本原则设计模式总览 引言 随着编码时间拉长&#xff0c;遇到的问题增加&#xff0c;发现设计模式对于解决某类场景问题确实帮助很大。其实在不了解设计模式之前&#xff0c;其设计思想也已经在日常开发中有所体现&#xff0c;只是没有总结出来。设计模式像是…

C语言-常量

什么是常量? 答:常量是在程序执行过程中,其值不发生改变的量,常量分为直接常量和符号常量两种。 其中直接常量又可以分为整型常量、实型常量、字符型常量、字符串常量。 直接常量 1.整型常量 整型常量即整数,包括正整数,负整数和0。c语言中常量可以用八进制,十进制和十六…

【网站项目】291校园疫情防控系统

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

The 2023 Guangdong Provincial Collegiate Programming Contest

I. Path Planning 嗯&#xff0c;怎么说呢&#xff0c;一般二维图&#xff0c;数据不是很大的比如n*m*log级别允许的&#xff0c;如果一眼不是bfs&#xff0c;可以考虑结合一下二分 本题可知&#xff0c;只能向下或者向右&#xff0c;那么我们就像如果答案为x&#xff0c;那么…

windows下使用压缩包安装mysql8.0数据库

获取安装包 可以访问mysql 官网下载压缩安装包 &#xff08;官网地址&#xff1a;https://downloads.mysql.com/archives/community/&#xff09; 根据自己的需要&#xff0c;下载对应mysql版本&#xff0c;我选择是是8.0.16版本 安装 解压之后&#xff0c;可以看到压缩包…

新概念英语1:Lesson7内容详解

新概念英语1&#xff1a;Lesson7内容详解 如何询问人的个人信息 本课里有两个关于个人信息的问句&#xff0c;一个是问国籍&#xff0c;一个是问工作&#xff0c;句型如下&#xff1a; what nationality are you?询问国籍 回复一般就是我是哪国人&#xff0c;I’m Chinese…

文章解读与仿真程序复现思路——中国电机工程学报EI\CSCD\北大核心《基于老化成本实时次梯度的异构储能系统功率分配策略》

本专栏栏目提供文章与程序复现思路&#xff0c;具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 论文与完整源程序_电网论文源程序的博客-CSDN博客https://blog.csdn.net/liang674027206/category_12531414.html 电网论文源程序-CSDN博客电网论文源…

【C++ 异或】奇数

异或知识&#xff1a;异或_百度百科 (baidu.com) 题目描述 给出 N 个正整数&#xff0c;其中只有一个数出现了奇数次&#xff0c;其余的数都出现偶数次。求那个出现了奇数次的数。 输入 第一行是一个整数 N&#xff1b; 第二行有 N 个正整数&#xff0c;两个整数之间用一个…

Vue3 大量赋值导致reactive响应丢失问题

问题阐述 如上图所示&#xff0c;我定义了响应式对象arrreactive({data:[]})&#xff0c;尝试将indexedDB两千条数据一口气赋值给arr.data。但事与愿违&#xff0c;页面上的{{}}在展示先前数组的三秒后变为空。 问题探究 vue3的响应应该与console.log有异曲同工之妙&#xff0…

如何系统的入门大模型?

GPT图解&#xff0c;从0到1构建大模型。 本书将以生动活泼的笔触&#xff0c;将枯燥的技术细节化作轻松幽默的故事和缤纷多彩的图画&#xff0c;引领读者穿梭于不同技术的时空&#xff0c;见证自然语言处理技术的传承、演进与蜕变。在这场不断攀登技术新峰的奇妙之旅中&#xf…

【非常好用的复制功能插件vue-clipboard2】

文章目录 前言一、vue-clipboard2是什么&#xff1f;二、使用步骤1.引入库2.在组件中使用 总结 前言 要实现功能是&#xff0c;点击按钮复制相对应的内容&#xff0c;复制到粘贴板&#xff0c;然后可以随意粘贴到任何地方。 一、vue-clipboard2是什么&#xff1f; 可以把内容…

如何进行软件测试

1、测试用例带给我们的好处 &#xff08;1&#xff09;测试执行者的依据 &#xff08;2&#xff09;使得工作可重复&#xff0c;自动化测试的基础 &#xff08;3&#xff09;评估需求覆盖率 &#xff08;4&#xff09;用例的复用 &#xff08;5&#xff09;积累测试的方法思…

嵌入式典型总线及协议

在嵌入式系统中&#xff0c;各种总线和通信协议扮演着关键的角色&#xff0c;它们连接和协调系统中的各种硬件组件&#xff0c;实现数据传输和控制。本文将介绍一些典型的嵌入式总线及其通信协议&#xff0c;以及它们在嵌入式系统中的应用。 以下是我整理的关于嵌入式开发的一…