【外企面试】求一个链表中环的入口【强势证实】

此题没有代码,是一道面试题。题目很好理解,有个链表,先判断是否有环,若是有环则求出环的入口。面试

这道题跟好几位offer收割机讨论过,基本都是已知leetcode或哪里的方法,证实该方法的正确性。指针

我和我家阳哥,试图证实,策略是能够推导出来的。证实以下:code

首先,要判断一个链表是否有环,机智的作法是快慢指针,令快指针fast每次走两步,慢指针slow每次走一步,那么fast若是能和slow相遇,就证实,链表中有环。leetcode

那么有环以后,如何寻找环的入口呢?ast

(1)首先,咱们定义几个变量:变量

  • ListHead表示链表头
  • RingEntry表示环入口指针
  • x表示ListHead与RingEntry之间的距离(两个相邻节点间的距离为1)
  • pos表示slow第一次走到RingEntry时,fast所在位置与RingEntry之间的距离,假设入环后顺时针走
  • y表示slow与fast的相遇点与RingEntry之间的距离
  • r表示环的长度(环中节点个数-1)

(2)其次,咱们须要证实一个结论---slow入环后,一圈以内一定与fast相遇List

         这个结论其实很好证实,咱们用反证法。假设slow走了一圈又回到了RingEntry,这一过程当中,都没与fast相遇。当slow回到RingEntry时,fast一定在距RingEntry为pos的位置。这一状态与slow刚入环时的状态同样,在这一圈中slow与fast都没有相遇,那么以后只会不断重复以前的路径,永不会相遇。方法

        由于咱们坚信 有环的话,slow和fast必相遇的,于是上述假设不成立,slow入环后,一圈以内一定与fast相遇。链表

(3)有了(2)的结论,就能够得出下列等式:co

  • slow首次到达RingEntry时,走了x步,此时fast应该走了2x的距离。又fast位于距离RingEntry为pos,那么:

   2x = x + k * r + pos(k表示fast在环中已经绕的圈数) ------>    pos = x - k * r

  • slow能够看作是比fast快了 r - pos步,又slow与fast相遇时,slow走了y步,于是有:

   2y - y = r - pos ------> y = r - pos

  • 从相遇点开始,slow至少再向前 r - y 步就能够到达环入口了,那么

     r - y = r - r + pos = pos = x - k * r ------> r - y + k * r = x

         之因此要把k * r移到 等号 的左边,是由于 k * r 表明着绕着环 k 圈,到达的位置仍是 r - y步后到达的位置。

根据最后一个等式,咱们就能够看出,slow再向前走 x 步 必定会到RingEntry。

因此寻找环入口的方式为:相遇点后,slow 从相遇点开始,tmp从 ListHead 开始,同时每次走一步,两个相遇点就是RingEntry!

相关文章
相关标签/搜索