zoukankan      html  css  js  c++  java
  • 有关有环链表的问题

    首先有三点要说明:

    1)在快指针追击慢指针时,如何保证快指针不会跨过慢指针而不会重合?

    快指针总是能和慢指针重合,为什么?因为如果假如真的“跨过了”,那么慢指针在i位置,快指针在i+1位置。但是考虑上一步,慢指针必定在i-1位置,快指针也在i-1位置,所以在上一步时已经重合了!

    2)为什么相遇时通过重置慢指针,然后让快慢指针以相同速度前进,再次相遇就是环的开始点?

    这就要分析一下走的过程了。因为快指针走的速度是慢指针的两倍,那么如果慢指针走p步,则快指针走了2p步。现在假设环的开始节点距离head节点有k个距离,则当慢指针走了k步时,慢指针正好到环的开始节点D,与此同时,快指针也走了2k步,前k步走在环外,后k步走在环内。由于k可能比环的长度还大,所以我们让k = k % LOOP_SIZE。

    现在有如下的结论:

    - 慢指针在环的开始处

    - 快指针在超前环k步的位置上

    - 慢指针落后k步于快指针

    快指针落后 LOOP_SIZE - k 步于慢指针!

    - 快指针以慢指针2倍的速度追击慢指针。或者说快指针以1步的相对速度追击相对静止的慢指针。则需要LOOP_SIZE-k 才能追上慢指针。在I位置追上。

    D -> I 的距离是 LOOP_SIZE - k, I -> D 的距离是k,这段距离恰好和A->D的距离相同,都是k !!!那么把慢指针放在head节点A,然后两个指针以相同速度前进,相遇处就是环的开始节点。

    3)一个推论:快慢指针第一次相遇的地方和head的距离是环长度的整数倍。

    假设相遇处离环开始点相距x个点,环长度为n个点
    慢指针:k+qn+x=m (1)
    又有2m-m=m=pn (2)
    有(1),(2)可得:k+qn+x=pn
    所以k+x = (p-q)n,即相遇处离head的距离为环长的整数倍.
    所以将其中一个指针移至head,同时两指针以相同速度再次相遇即为环的开始处.

    1.如何判断一个链表中有环

    使用两个slow, fast指针从头开始扫描链表。指针slow 每次走1步,指针fast每次走2步。如果存在环,则指针slow、fast会相遇;如果不存在环,指针fast遇到NULL退出。

    就是所谓的追击相遇问题:

    2.求有环单链表的环长

    在环上相遇后,记录第一次相遇点为Pos,之后指针slow继续每次走1步,fast每次走2步。在下次相遇的时候fast比slow正好又多走了一圈,也就是多走的距离等于环长。

      设从第一次相遇到第二次相遇,设slow走了len步,则fast走了2*len步,相遇时多走了一圈:

        环长=2*len-len。

    3.求有环单链表的环连接点位置

      第一次碰撞点Pos到连接点Join的距离=头指针到连接点Join的距离,因此,分别从第一次碰撞点Pos、头指针head开始走,相遇的那个点就是连接点。

    参考网址:http://www.cnblogs.com/xudong-bupt/p/3667729.html

           http://www.2cto.com/kf/201403/282309.html

  • 相关阅读:
    java根据汉字获取全拼和首字母
    SQL 增加或删除一列
    C#实现WinForm传值实例解析
    C# 静态类与非静态类、静态成员的区别分析
    c# 面相对象1-概括
    c# 面相对象2-之封装性
    c# 面相对象3-之继承性
    面向对象基础知识(含义、修饰符、三大特性)
    c# 面相对象4-多态性
    用集合求平均分
  • 原文地址:https://www.cnblogs.com/churi/p/3886043.html
Copyright © 2011-2022 走看看