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 }
以上是关于Leetcode:Linked List Cycle II的主要内容,如果未能解决你的问题,请参考以下文章
[leetcode]Linked List-237. Delete Node in a Linked List
leetcode — linked-list-cycle-ii
LeetCode-Palindrome Linked List