快慢指针在链表中的应用

来源:互联网 发布:知乎更新图标 编辑:程序博客网 时间:2024/05/16 18:30


 链表的操作题有很多,最常见的莫过于,单链表的反转之类,这里仅对可以用快慢指针来解决的题目进行解析。
        1、判断单链表中是否存在有环,如果有的话,找出这个环的入口节点;
        2、取单链表的中间节点;
        3、判断两个单链表是否相交,如果相交,找到交点;
解析:
      1、判断单链表中是否存在有环,如果有的话,找出这个环的入口节点;
      判断单链表是否存在环,使用快慢指针是比较明智的做法,设置两个指针,一个 fast,每次走两步,一个slow 每次走一步,直到 fast == slow 或者 链表结束。当 fast == slow 的时候,即存在环。
      如何找到环的入口节点?这里需要一个推理证明:
      假设起点是head,换入口点是entry,相遇点是meet,链表总长度是length,相遇时慢指针走了step 步,相遇时,快指针已经在环里转了N圈了,圈长是round,那么根据快慢指针的原理应该可以推断出这样的等式:
                     2*step = step + N*round  ==> step = N * round
       再设定变量 head_entry = 链表起点到环入口点的距离,entry_meet 为 环入口点到相遇点的距离,meet_entry 为相遇点到环入口点的距离,那么应该有:
                    round = length - head_entry
                    step = head_entry + entry_meet
                    meet_entry = length - head_entry - entry_meet
             由于 
                    step = N * round
             推出
                    step = N * round 
                            = (N -1) * round + round 
                            = ( N - 1) * round + length - head_entry
                            = head_entry + entry_meet
             进一步,得出:
                    head_entry = ( N - 1) * round + ( length - head_entry - entry_meet )
                                      = ( N - 1 ) * round + meet_entry
             得出以下结论:head 到 entry 的距离,等于 整数倍圈长 + 相遇点到环入口点的距离
             则设置两个指针,一个从链表起点出发,一个从相遇点触发,根据推理出来的公式,在第一次相遇时,相遇点出发的指针一定在圈内转了N圈,且走过了从相遇点到环入口点的距离,正好落在环入口点上,所以:
              从链表起点出发的指针和从相遇点出发的指针,第一次相遇的点就是环的入口点。
      2、取单链表的中间节点
      这是一个不错的题目,最简单的实现方式就是遍历两次,一次计算链表长度,再一次找到中间结点。但是如果链表比较长的话,这样遍历两次是比较不划算的,这里可以用到快慢指针,实现一次遍历即可找到中间节点。
      原理很简单,fast 和 slow 两个指针,因为已确定这个单链表里没有环,让fast 每次走两步,slow 每次走一步,则当fast 走完的时候,slow 正好走到链表的中间位置。
      3、判断两个单链表是否相交,如果相交,找到交点;
      这个问题需要先明确是单链表,所以发生的相交情形只有两种,丁字相交 和 一字相交,十字相交是不可能的,因为只有一个next 指针。
      这里可以利用 第一题 中的探测环的方式。我们假设两个链表分别是 A 和 B,然后将 A  的收尾相接,就可以得到一个环,然后从B 链表开始,使用快慢指针探测是否有环存在,如果相交,则必然可以探测到环。
      探测到之后,如何确定交点呢?
      这个还是利用第一题中的探测环的入口点是一样的了,因为交点必然是 B中 的环入口点。

      同样 从B 的起点 和 fast 与 slow 指针的交点分别设置两个指针,每次都走一步,第一次相遇的点就是 交点

0 0
原创粉丝点击