Linked List Cycle

来源:互联网 发布:如何解绑淘宝手机号码 编辑:程序博客网 时间:2024/06/14 05:13

题目:给你一个单链表链表,判定该链表是否存在循环链表于其中

我开始是想通过遍历,如果没有next域为空肯定是循环链表,但是问题是我跟本不知链表的终点,又想了一些其他的方法都没有可行性,又不想用双重循环来判定

后来找到了下面的方法,利用快慢指针,如果是循环的链表,二者肯定会在某一点相遇,代码如下

public boolean hasCycle(ListNode head) {        if(head==null) return false;        ListNode walker = head;        ListNode runner = head;        while(runner.next!=null && runner.next.next!=null) {            walker = walker.next;            runner = runner.next.next;            if(walker==runner) return true;        }        return false;    }

升级版是寻找到循环起点:下面是别人的分析

假设刚进环的时候慢指针走了m步,环的大小为n,快慢指针在距离环起点x步的时候相遇。慢指针是一定走不完一圈就会和快指针相遇的(因为最惨的情况下就是慢指针进圈的时候快指针在它前面一个,快指针速度时慢的两倍,这种悲剧情况下慢指针也不可能走完一圈就会被追到)。这是慢指针走了m+x步,快指针走了2(m+x)步,快指针在圈内走了2(m+x)-m=m+2x步。由于相遇在x位置,所以 m+2x % n = x,推出m+2x = i * n + x,于是m+x = i*n。我们注意到慢指针已经走了x步了,再走m步时一定会回到圈的起点的(m+x = i*n),所以等它们相遇后,一个指针从head开始走,然后慢指针从相遇的位置出发,则一定会相遇到圈的起点

public ListNode detectCycle(ListNode head) {    ListNode p1 = head;    ListNode p2 = head;    while(p2 != null && p2.next != null){        p1 = p1.next;        p2 = p2.next.next;        if (p1 == p2) break;    }    if (p2 == null || p2.next == null){        return null;    }    p1 = head;    while(p1 != p2){        p1 = p1.next;        p2 = p2.next;    }    return p2;}


0 0
原创粉丝点击