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

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

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

我和我家阳哥,试图证明,策略是可以推导出来的。证明如下:

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

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

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

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

(2)其次,我们需要证明一个结论---slow入环后,一圈之内必定与fast相遇

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

        因为我们坚信 有环的话,slow和fast必相遇的,因而上述假设不成立,slow入环后,一圈之内必定与fast相遇。

(3)有了(2)的结论,就可以得出下列等式:

  • 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!

   

 

posted on 2017-05-12 19:44  GyyZyp  阅读(381)  评论(0编辑  收藏  举报

导航