题目描述
给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。
解题思路
使用快慢指针法。有两种做法:
方法一(推荐)
- 判断是否有环。设置快慢指针,快指针每次走两步,慢指针每次走一步,若快慢指针相遇,则说明该链表包含环。记录相遇结点,停止快慢指针;
找出环的入口。设置两个指针,一个指针位于链表头,一个指针位于相遇点,同时开始,每次都走1步,相遇时,相遇点即为环的入口。原理如下:
原理:设从链表头到环的入口长度为$s_a$,从环的入口到相遇点长度为$s_m$,环的长度为$s_c$。则到快慢指针相遇时,$S_{fast}=s_a+ms_c+s_m$,$S_{slow}=s_a+ns_c+s_m$,其中$m$和$n$是非负整数。因为$S_{fast}=2S_{slow}$,则可推出$s_a=(m-2n)s_c-s_m=(m-2n-1)s_c+s_c-s_m$,而$s_c-s_m$为相遇点到环入口剩下的长度,所以相遇点的指针和从头部走的指针总会在环的入口相遇,或走0圈,或1圈……
- 方法二
- 判断是否有环。设置快慢指针,快指针每次走两步,满指针每次走一步,若快慢指针相遇,则说明该链表包含环。记录相遇结点,停止快慢指针;
- 判断环内有多少个结点。设置一个指针指向相遇点,从相遇点开始走,如果再次回到相遇点,则说明已经走了一圈,可得到环内的结点数
count
;
- 找出环的入口。设置两个指针指向链表头,其中一个指针先走
count
步,然后同时开始走,若两个指针相遇,相遇点即为环的入口。
代码
Python(2.7.3)
方法一(推荐)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
class Solution: def EntryNodeOfLoop(self, pHead): if pHead is None or pHead.next is None or pHead.next.next is None: return fast, slow = pHead, pHead while fast.next.next != slow.next: fast = fast.next.next slow = slow.next if fast.next is None or fast.next.next is None: return meet = slow.next p0 = pHead while p0 != meet: p0 = p0.next meet = meet.next return p0
|
运行时间:24ms
占用内存:5748k
方法二
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
|
class Solution: def EntryNodeOfLoop(self, pHead): if pHead is None or pHead.next is None or pHead.next.next is None: return fast, slow = pHead, pHead while fast.next.next != slow.next: fast = fast.next.next slow = slow.next if fast.next is None or fast.next.next is None: return circle = slow.next count = 1 while circle.next != slow.next: count += 1 circle = circle.next p1, p2 = pHead, pHead step = 0 while step != count: step += 1 p1 = p1.next while p1 != p2: p1 = p1.next p2 = p2.next return p1
|
运行时间:30ms
占用内存:5696k