判断链表成环,且找出环的起点

来源:互联网 发布:jre 7u9 windows i586 编辑:程序博客网 时间:2024/05/16 14:37

判断链表成环,且找出环的起点。

  • 判断链表成环
  • 找出环的起点
  • Java代码实现

1. 判断链表是否成环

Floyd环判断法:从同一个起点同时开始以不同速度前进的2个指针最终相遇,那么可以判定存在一个环。

设想:乌龟和兔子在同一个环上赛跑,跑的快的兔子速度为2,跑的慢的乌龟速度为1,则兔子终会赶上乌龟。

理解:如果以乌龟为参考对象,则兔子前进的速度为1,这就意味着,兔子必将赶上乌龟。

所以一个判断成环的方法是:先舍子两个指针都指向表头,其中p1每次前进一个节点,p2每次前进两个节点,且p1和p2同时走,当p2指向的地址为null,就证明链表没有环。如果在某个时刻,p1和p2指向的地址相同,那么链表就是有环的。

2.找出环的起点

这里写图片描述
同时可以进一步考虑:K1是等于零的,也就是p1在进入环后,走了不到一圈就在交点处和p2重合。因为p1在进入环的时候,p2和p1之间的距离(沿着行走方向)至多为 d2-1,不可能超过d2-1,因为环的大小也才只有d2 。p2追赶p1,最多只需要走d2-1步,因为每走一步,p1和p2的相对距离减小1,那么p1最多只走了d2-1步,就是最多只经过了d2-1个节点,不可能走完一圈。
这里写图片描述
最后推出的式子的含义可以理解为:d1的长度 = 环长度的整数倍 + 交点与环入口的距离
所以我们可以得出:当p1和p2相遇后,让p1回到原点,p2在相遇点,且两者每次都前进一个节点,当两者再次相遇时,就是环的起点。

3. Java代码实现

int FindBeginLoop(ListNode head){    ListNode p1 = head, p2 = head;    boolean loopExists = false;    if(head == null)        return false;    //判断环是否存在    while(p2.getNext()!=null&&p2.getNext().getNext()!=null){        p1 = p1.getNext();        p2 = p2.getNext().getNext();        if(p1==p2)            loopExists = true;            break;    }    //如果环存在,寻找环的起点    if(loopExists){        p1 = head;        while(p1!=p2){            p1 = p1.getNext();            p2 = p2.getNext();        }        return p1;    }    return null; //不存在}//附:定义的LitNode类public class ListNode {    private int data;    private ListNode next;    public ListNode(int data) {        this.data = data;    }    public int getData() {        return data;    }    public void setData(int data) {        this.data = data;    }    public SingleListNode getNext() {        return next;    }    public void setNext(SingleListNode next) {        this.next = next;    }}
参考

http://www.cnblogs.com/snake-hand/p/3148328.html

原创粉丝点击