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

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

  • 判断链表成环
  • 找出环的起点
  • 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

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值