zoukankan      html  css  js  c++  java
  • 【外企面试】求一个链表中环的入口【强势证明】

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

    这道题跟好几位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!

       

  • 相关阅读:
    Python3.x基础学习-静态方法和类方法
    Python3.x基础学习-@property
    Python3.x基础学习-装饰器
    SpringMVC学习(七)
    SpringMVC学习(六)
    SpringMVC学习(五)
    整合SSM(二)
    整合SSM(一)
    SpringMVC学习(四)
    SpringMVC学习(三)
  • 原文地址:https://www.cnblogs.com/xiaozhuyang/p/6847033.html
Copyright © 2011-2022 走看看