技术宅小伙:计算机新手学习系列之LeetCode!

哈喽大家好,我是技术宅小伙。

自从上次发了这个入门系列后,出乎我的意料,这个系列居然是最受欢迎的。我各种被催更,呼声最高的就要数数和图的题了。那今天就给大家带来一道基础的图吧,让我们一起来看一下 Lico 第 1971 题 fine if path existing graph。

这道题的题目是说,已知一个有 n 个节点的双向的图(双向也可以是无向),它的每一个节点都从 0 标记到 n 减 1,又已知一个 2 滴的 integer r 来记录这个 graph edges。这个 already 的每一个 element 都记录着这一个边所连接的两个 vertex。每两个节点之间最多只会有一条边,并且没有任何节点会有指向自己的边。

我们现在需要判断的是,在这幅图里,有没有一条可以从起点通往终点的路径。如果有这个路径我们就返回 true,没有这个路径我们就返回 false。

从第一个例子里就可以看出,这道题只是想让我们判断有没有可行的路径,并没有让我们找出最短路径,所以这道题只需要一个最简单的便利就好了。那我们先用 breath-for-search 来做吧。题目给出的例子太简单了,让我们自己来举一个稍微复杂一点的例子来做这道题。

比如我们现在有这样的一组编,他画出来图是这样的,我们的 source 是 0,the destination 是 4。来到这个 h 的数组,我们现在暂时还没有办法很有效率的利用它,但我们可以先用它来建一个 adjacent 的 list,也就是把每一个节点的相邻节点都找出来,并放进一个 list 里。然后所有这些节点的这些 list 都按着顺序来放进一个更大的 list 里。

所以我们现在先建一个有 n 个空 list 的大 list,initialize 好了这个 adjacent list 后,我们就可以一个一个的来 process 就是 edge 了。每拿出一个 edge,我们就把这两个节点放进对方的 list 里,比如取出零一就先把 0 放进 1 的 list,1 放进 0 的 list,再取出 03 也一样把 0 放进 3 的 list,3 放进 0 的 list,然后继续 121324,最后二三结束后,这个 adjacent list 里就存放着每一个节点的邻居们了,比如 0 连着 1、2,1 连着 0、2、3,以此类推。

听好这个 adjacent list 后,我们就可以开始 search 了。因为这个是 graph,所以里面可能会有环,为了不进入环里并且无限循环下去,我们需要记录一下哪些节点是我们已经见到过了的,再记录一下哪些节点是接下来要做对比的。

因为是 BFS 嘛,我们就先建一个 queue(first in first out)并且把这个 source 放进去作为第一个 element,再来记录一下我们已经见过了哪些,因为这个 queue 记录的是我们将要去做对比的 element,所以我们这里需要用一个 while loop 来看一下这个 queue 里面还有没有剩余的 element。如果 queue 不是空的话,也就是说里面还有 element 需要我们继续去做对比的话,我们就继续录下去。从 queue 里面取出第一个 element 来作为当前的节点。如果当天这个节点它就是 destination 的话,那说明我们已经找到了一条可通行的路径了,这时候我们就只需要返回 true 就好了。如果它并不是 destination 的话,那这时候我们就得继续找下去。

我们就把它的邻居再放进这个 queue 里面。但我们不能盲目的把它们全部都扔进 queue 里,因为这个邻居可能是我们已经见过的节点,我们不想要进入一个循环,然后一直不停的循环下去。所以我们要先确认一下这些邻居是我们没有见到过的,它是我们没有见过的我们再放进 queue 里,然后这时我们已经见过了,所以我们再把它给加入 visit。

好了,这个循环他就可以一直不停的找下去,直到他找到了一条可通行的路径或者他的 queue 里面没有任何东西可以看了,就像第二个 example 里面一样,我们的 source 所在的这个 subgraph 里面,他的所有节点都被我们看完了,但是他还是没有找到他的 destination,那么就证明这个 source 和 destination 之间没有任何一条联通的路,我们就可以返回 false 了。

要提到这里大致的逻辑已经出来了,但是有一个 case 我们并没有考虑到。因为每个节点它都不会有一条通向自己的边,所以如果它的 root 和 destination 是同一个节点的话,这个情况会被漏掉。最简单的修改就是直接在最开始做一个判断,如果他俩相等的话,这个图里也是有可通行的路径的,并且这个路径只包含一个 vertex。

好啦,现在我们应该是做完了。这个文章如果对你有所帮助的话,记得点赞收藏转发。什么地方我没有讲清楚的话,记得在弹幕或评论区里告诉我。我是不会写代码的,阿静我们下个文章见,拜拜!

大家好,我是技术宅小伙。

自从上次发了这个入门系列后,出乎我的意料,这个系列居然是最受欢迎的。我各种被催更,呼声最高的就要数数和图的题了。那今天就给大家带来一道基础的图吧,让我们一起来看一下 Lico 第 1971 题 fine if path existing graph。

这道题的题目是说,已知一个有n个节点的双向图(双向也可以是无向),它的每一个节点都从0标记到n 减1,又已知一个2元的integer r来记录这个图的边。这个already的每一个element都记录着这一个边所连接的两个vertex。每两个节点之间最多只会有一条边,并且没有任何节点会有指向自己的边。

我们现在需要判断的是,在这幅图里,有没有一条可以从起点通往终点的路径。如果有这个路径我们就返回true,没有这个路径我们就返回false。

从第一个例子里就可以看出,这道题只是想让我们判断有没有可行的路径,并没有让我们找出最短路径,所以这道题只需要一个最简单的遍历就好了。那我们先用BFS来做吧。题目给出的例子太简单了,让我们自己来举一个稍微复杂一点的例子来做这道题。

比如我们现在有这样的一组编,他画出来图是这样的,我们的source是0,the destination是4。来到这个h的数组,我们现在暂时还没有办法很有效率的利用它,但我们可以先用它来建一个adjacent的list,也就是把每一个节点的相邻节点都找出来,并放进一个list里。然后所有这些节点的这些list都按着顺序来放进一个更大的list里。

所以我们现在先建一个有n个空list的大list,initialize好了这个adjacent list后,我们就可以一个一个的来process就是edge了。每拿出一个edge,我们就把这两个节点放进对方的list里,比如取出零一就先把0放进1的list,1放进0的list,再取出03也一样把0放进3的list,3放进0的list,然后继续121324,最后二三结束后,这个adjacent list里就存放着每一个节点的邻居们了,比如0连着1、2,1连着0、2、3,以此类推。

听好这个adjacent list后,我们就可以开始search了。因为这个是graph,所以里面可能会有环,为了不进入环里并且无限循环下去,我们需要记录一下哪些节点是我们已经见到过了的,再记录一下哪些节点是接下来要做对比的。

因为是BFS嘛,我们就先建一个queue(first in first out)并且把这个source放进去作为第一个element,再来记录一下我们已经见过了哪些,因为这个queue记录的是我们将要去做对比的element,所以我们这里需要用一个while loop来看一下这个queue里面还有没有剩余的element。如果queue不是空的话,也就是说里面还有element需要我们继续去做对比的话,我们就继续录下去。从queue里面取出第一个element来作为当前的节点。如果当天这个节点它就是destination的话,那说明我们已经找到了一条可通行的路径了,这时候我们就只需要返回true就好了。如果它并不是destination的话,那这时候我们就得继续找下去。

我们就把它的邻居再放进这个queue里面。但我们不能盲目的把它们全部都扔进queue里,因为这个邻居可能是我们已经见过的节点,我们不想要进入一个循环,然后一直不停的循环下去。所以我们要先确认一下这些邻居是我们没有见到过的,它是我们没有见过的我们再放进queue里,然后这时我们已经见过了,所以我们再把它给加入visit。

好了,这个循环他就可以一直不停的找下去,直到他找到了一条可通行的路径或者他的queue里面没有任何东西可以看了,就像第二个example里面一样,我们的source所在的这个subgraph里面,他的所有节点都被我们看完了,但是他还是没有找到他的destination,那么就证明这个source和destination之间没有任何一条联通的路,我们就可以返回false了。

要提到这里大致的逻辑已经出来了,但是有一个case我们并没有考虑到。因为每个节点它都不会有一条通向自己的边,所以如果它的root和destination是同一个节点的话,这个情况会被漏掉。最简单的修改就是直接在最开始做一个判断,如果他俩相等的话,这个图里也是有可通行的路径的,并且这个路径只包含一个vertex。

好啦,现在我们应该是做完了。这个文章如果对你有所帮助的话,记得点赞收藏转发。什么地方我没有讲清楚的话,记得在弹幕或评论区里告诉我。我是不会写代码的,阿静我们下个文章见,拜拜!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

技术宅小伙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值