首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >微信一面,被问懵了!

微信一面,被问懵了!

作者头像
五分钟学算法
发布2022-04-08 16:05:55
发布2022-04-08 16:05:55
6470
举报
文章被收录于专栏:五分钟学算法五分钟学算法

大家好,我是吴师兄。

前几天有个训练营的小伙伴跟我说,他去微信面试的时候被环形链表这道题目问懵了。

我一听,直接一连串问号过去:这道题目不是重点题目么? 直播的时候强调过好几次!

他赶忙回应:代码都写对了,为什么相遇也回答对了,但关于为什么设置 fast 指针每次移动 2 步,能不能移动 3、4、5...步等延伸问题没回答出。

这个就是我的锅,没把这个问题加上去,索性今天也给大家分享一下,一个个来回答下方的问题。

  • 1、当 slow = 1 , fast = 2 ,为什么 fast 和 slow 一定会相遇?
  • 2、当 slow = 1 , fast = 2 ,fast 和 slow 相遇时,slow 指针是否绕环超过一圈?
  • 3、slow 和 fast 的移动步数有什么规则?
  • 4、能否设置为 slow 每次移动 1 步,fast 每次移动 3、4、5...步?
  • 5、为什么设置 slow = 1 , fast = 2 ?
  • 6、为什么得出相反的结论?

为了方便大家理解与表达,所以回答尽可能的采取口语化的表达方式,面试的时候你直接拿去用就行。

1、当 slow = 1 , fast = 2 ,为什么 fast 和 slow 一定会相遇?

首先,我们从现实角度去思考。

一个 400 米的圆形跑道上,有跑的慢的人、有跑的快的人,只要给予一定的时间,快的肯定会追上慢的,触发相遇。

环形链表在这个的基础上增加了一条限制:跑道并非连续,而是有一个个的节点组成的

需要注意,如果两者没有在节点相遇,而是在节点与节点之间的位置相遇,那并非相遇只是相交

1、假设,fast 在 slow 后方一个节点的位置,那么它们都跳一次之后,fast 和 slow 相遇了。

2、假设,fast 在 slow 后方两个节点的位置,那么它们都跳一次之后,fast 和 slow 的距离缩短为 1,变成了上述假设 1 的问题,可以相遇。

3、假设,fast 在 slow 后方 N 个节点的位置,那么它们都跳一次之后,fast 和 slow 的距离缩短为 N - 1,每条一次,都可以缩短一个单位,不断缩短,最终变成上述的假设 1。

所以,fast 和 slow 一定会相遇

2、当 slow = 1 , fast = 2 ,fast 和 slow 相遇时,slow 指针是否绕环超过一圈?

从 slow 进入环之后开始统计,fast 与 slow 相距最远的距离是 fast 在 slow 前方一个节点的位置。

此时,假设一下,fast 与 slow 同时在节点 2 开始出发,相当于两者相距一个环的距离。

当 slow 跑完一圈来到起始位置节点 2 时,由于 fast 速度是 slow 的两倍,那么 fast 必然跑了两圈也来到起始位置节点 2 ,两者相遇。

而此时,fast 在 slow 的前方位置,意味着两者的距离是小于一个完整的环的节点数的,说明 fast 可以更快的追上 slow。

既然 fast 与 slow 相距一个环的距离相遇时,slow 才能跑一圈,那么相距更短的距离,slow 没有跑完一圈,两者相遇了。

3、slow 和 fast 的移动步数有什么规则?

只需要两者的步数不一致就行。

4、能否设置为 slow 每次移动 1 步,fast 每次移动 3、4、5...步?

先说答案:可以

首先,只要快慢两个指针都进入环中,两者有速度差,快指针就一定能够追上慢指针。

追上可以分为两种情况:

1、恰好追上,即快慢指针在某个位置相遇了 2、快指针超过了慢指针,快指针跑到了慢指针的前面了

所以,我们需要分析的就是第二种情况:跑到前面之后能否多跑几圈之后刚好相遇

假设环的周长为整数 L,slow 每次走 a 步,fast 每次走 b 步,a ≠ b。

进入环后开始统计,相遇时两者都走了 t 次,如果把环拉成一根直线,相当于 fast 在距离 slow 为 t * (b – a ) 这样远的距离开始追击,每次追近 b – a 步,追了 t 次追上了。

那么 t * (b – a ) / L 就是 fast 需要跑多少圈才能追上 slow 并刚好相遇的答案。

n 表示圈数,为整数才合理。

因为如果 n 不是整数,代表 fast 和 slow 不在某个节点相遇,而是在节点与节点之间的位置相遇了。也就是说 n = t * (b – a ) / L 。

很显然,L 为常数值,(b – a ) 为常数值,必然可以找到 t,使得 t * (b – a ) 是 L 的倍数。

由此也证明了 slow 每次走 1 步,fast 每次走 2 步、3 步、4 步。。。都是可以相遇的。

甚至,slow 每次走 2 步,fast 每次 3 步、4 步。。。都是可以相遇的。

只要 a ≠ b,存在步数差。

5、为什么设置 slow = 1 , fast = 2 ?

由于 n = t * (b – a ) / L 。

则 n 越小越合适,也就是希望 t * (b – a ) 越小,希望 b – a 越小,因为 b 和 a 才是我们可以控制的。

由此 b – a = 1 是一个最小的答案,即 fast 和 slow 相差一步最合理

然后,再来看,slow 进环的时候,fast 已经在环里面了,当 slow 来到环入口的时候,代表 fast 已经跑了一圈。

所以,fast 和 slow 相遇,n 至少为 1。

n 越小,fast 总共走的路程就越小,时间复杂度就越低。

所以,n = 1 时最低的时间复杂度。

所以,fast 跑的越慢,越能在环中少跑几圈等到还在外面直线跑的 slow。

由于 a ≠ b, b – a = 1 ,a = 1,所以 b = 2。

所以,设置 slow 为 1 ,fast 为 2 最合理!

6、为什么得出相反的结论?

关于 fast 与 slow 能否相遇的问题,我在网上看到这样的回答。

仔细看看,是不是很有道理,但得到的结论却和本文问题 4 得出的结论不符。

谁是对的呢?

我们顺着它的假设来模拟一下。

假设环的周长为偶数,也就是六个节点。

并且进入环后 slow = 1 ,fast = 3,slow 与 fast 的距离为奇数。

模拟一下,fast 始终会出现在节点 4 和节点 1 这两个位置,当 slow 重新来到节点 1 的时候,fast 又来到了节点 4,如此反复,两者无法相遇

这个结论是对的??!!

这种假设根本就不会成立!

即进入环后 slow = 1 ,fast = 3,slow 与 fast 的距离为奇数这种假设无法成立。

在进入环之前,slow 和 fast 有一段公共的直线路需要走。

假设这条直线的长度为 m。

那么 slow 需要跳 m 次才能来到环入口位置节点 1 ,fast 需要跳 m/3 次才能第一次来到环入口位置节点 1,环的节点数是 6 个,fast 跑 2 次可以跑完一圈,假设跑了 n 圈,那么就跑了 2n 次,那么再跑一次就来到了节点 4 。

于是有了等式:m = m / 3 + 2n + 1

计算一下得 n = ( 2m / 3 - 1 ) / 2

由于 2m 为偶数,根据数学知识一个能被 3 整除的偶数除以 3 仍为偶数,于是 2m / 3 为偶数,2m / 3 - 1 为奇数, ( 2m / 3 - 1 ) / 2 无法是整数。

所以,找不到这样一个整数 m 和整数 n,使得上面的假设成立

假设不成立,结论也不成立!

当然,还存在更严谨的数学证明,感兴趣的小伙伴可以搜一下裴蜀定理、线性同余方程等数学知识。

搞定!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-03-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 五分钟学算法 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、当 slow = 1 , fast = 2 ,为什么 fast 和 slow 一定会相遇?
  • 2、当 slow = 1 , fast = 2 ,fast 和 slow 相遇时,slow 指针是否绕环超过一圈?
  • 3、slow 和 fast 的移动步数有什么规则?
  • 4、能否设置为 slow 每次移动 1 步,fast 每次移动 3、4、5...步?
  • 5、为什么设置 slow = 1 , fast = 2 ?
  • 6、为什么得出相反的结论?
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档