Leetcode:Linked List Cycle II

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Leetcode:Linked List Cycle II相关的知识,希望对你有一定的参考价值。

题目大意:判断一个链表是否含有环,如果有环则输出距离链表头最近的环上结点(即从链表头出发进入环的入口)。


  有趣的题目,一般判断链表是否有环可以同时使用两个轨迹结点遍历整个链表,且轨迹结点速度不同,快者q每次循环移动两步,慢者s每次循环移动一步。这样如果有环,那么快者必定会在环上追赶上慢者(由于二者相对速度为1,故快者不可能越过慢者),而且快者和慢者必定会在n次循环内相遇(或者快者遇到null),n为链表的长度。

  下面说一下如果获得距离链表头最近的结点。假设环的入口距离链表头n个结点,而q与s在距离环入口m个结点处相遇,q与s在第k次循环相遇。由于慢者在进入环时快者已经进入,故慢者不可能完全遍历环,由此可以得出n+m=k。前面提到的所有变量只有k是已知的,我们的目标是求出n。

  先假设环由c个结点组成,可以推出:$$ 2k-L=k-L\left(mod\ c\right)\Rightarrow n+m=pc $$

  这也意味着当一个轨迹结点从快者和慢者相遇处出发,每次循环前进一步,在n次循环后将回到环的入口处。虽然我们不知道n的具体值,但是请查看n的定义,是入口距离链表头的距离,因此当我们设置两个轨迹结点x和y同时分别从相遇处和链表头出发,当二者首次相遇时,就是环处,所移动的步数,就是环距离链表头的距离。

  利用这个算法,可以在O(n)时间复杂度内(n为链表中包含的结点数)找到环的入口(两次循环操作的时间复杂度都不超过O(n)),空间复杂度由于只使用了常量个变量故为O(1)。


技术分享
 1 public class Solution {
 2     public ListNode detectCycle(ListNode head) {
 3         if(head == null || head.next == null)
 4         {
 5             return null;
 6         }
 7         
 8         ListNode fast = head.next.next;
 9         ListNode slow = head.next;
10         
11         while(fast != slow)
12         {
13             if(fast == null || fast.next == null)
14             {
15                 return null;
16             }
17             fast = fast.next.next;
18             slow = slow.next;
19         }
20         
21         ListNode a = head;
22         ListNode b = slow;
23         
24         while(a != b)
25         {
26             a = a.next;
27             b = b.next;
28         }
29         return a;
30     }
31 }
View Code

 

以上是关于Leetcode:Linked List Cycle II的主要内容,如果未能解决你的问题,请参考以下文章

[leetcode]Linked List-237. Delete Node in a Linked List

leetcode — linked-list-cycle

leetcode — linked-list-cycle-ii

LeetCode-Palindrome Linked List

Leetcode: Linked List Random Node

LeetCode-Remove Linked List Elements