部分文章内容为公开资料查询整理,原文出处可能未标注,如有侵权,请联系我,谢谢。邮箱地址:gnivor@163.com ►►►需要气球么?请点击我吧!

*LeetCode--142. Linked List Cycle II (找出循环链表的循环头部)

问题大意:给定一个链表,找到链表循环部分的头部。如果不存在循环,返回null。

找链表头部的方法:

链表头是X,环的第一个节点是Y,slow和fast第一次的交点是Z。各段的长度分别是a,b,c,如图所示。环的长度是L。slow每次前进1个元素,fast每次前进两个元素。

首先给出判别链表是否有环的方法:使用两个指针slow,fast。两个指针都从表头开始走,slow每次走一步,fast每次走两步,如果fast遇到null,则说明没有环,返回false;如果slow==fast,说明有环,并且此时fast超了slow有n圈,返回true。

拓展:确定循环部分的长度: 在两个指针相交后,fast停止,slow继续向前,并且计数。当slow==fast时,即可得到循环部分的长度。


那么如何得到循环部分的头部?

slow走过的路程:a+b
fast走过的路程:a+b+n*(b+c)

由于fast的速度是slow的2倍,有 2*(a+b) = a+b+n*(b+c)   得到 a = n(b+c) - b;
a = c+(n-1)*(b+c)  即a的路程=c+(n-1)圈循环部分的路程
因此想要得到循环部分的开始,可以令一个指针从头部开始,另一个指针从z开始,每次移动1步,最终相交的位置就是循环头部。

public static ListNode detectCycle(ListNode head) {
    if (head == null)
        return null;
    ListNode p1 = head;
    ListNode p2 = head;
    do{
        if (p1 != p2) {
            p1 = p1.next;
            p2 = p2.next.next;
        }else{
            break;
        }
    } while(p2 != null && p2.next != null); 
    System.out.println(p1.val+" "+p2.val); //首次相交的位置
    if(p1==p2){
        ListNode start = head;
        while(start!=p1){
            System.out.println(start.val);
            start = start.next;
            p1 = p1.next;
        }
        return p1;
    }
    return null;
}

 

posted @ 2015-07-20 20:38  流了个火  阅读(315)  评论(0)    收藏  举报
►►►需要气球么?请点击我吧!►►►
View My Stats