#142 Linked List Cycle II
Given the
head
of a linked list, return the node where the cycle begins. If there is no cycle, returnnull
.There is a cycle in a linked list if there is some node in the list that can be reached again by continuously following the
next
pointer. Internally,pos
is used to denote the index of the node that tail'snext
pointer is connected to (0-indexed). It is-1
if there is no cycle. Note thatpos
is not passed as a parameter.Do not modify the linked list.
解题思路:
方法1.还是visited存见过的点,再次见就是环入口。
方法2.慢指针和快指针相遇的点与链表开始的点同时往前进1,相遇的地方为环的入口。
方法2的推理过程:
先看环在不在,不在就return None。
在的话,链表开始的点距离环入口为F。而环上有C个点。快指针和慢指针相遇的地方距离环入口为A。A + B = C. B为环减去相遇点剩下的点。
一直快指针步速是慢指针的2倍。所以F+A= (F + A + nC)/2.
推出F + a = nC。当C > F时,n=1,那么C - A = B,B自然也等于F。所以相遇的地方为环的入口。
当C < F 时,那么 F = B + nC. 相遇的点还是环的入口。
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def detectCycle(self, head: Optional[ListNode]) -> Optional[ListNode]:
visited = set()
while head:
if head in visited:
return head
visited.add(head)
head = head.next
return None
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def detectCycle(self, head: Optional[ListNode]) -> Optional[ListNode]:
slow = fast = slow2 = head
while fast and fast.next:
fast = fast.next.next
slow = slow.next
if fast == slow:
while slow != slow2:
slow2 = slow2.next
slow = slow.next
return slow
return None
#160 Intersection of Two Linked Lists
Given the heads of two singly linked-lists
headA
andheadB
, return the node at which the two lists intersect. If the two linked lists have no intersection at all, returnnull
.For example, the following two linked lists begin to intersect at node
c1
:
The test cases are generated such that there are no cycles anywhere in the entire linked structure.
Note that the linked lists must retain their original structure after the function returns.
Custom Judge:
The inputs to the judge are given as follows (your program is not given these inputs):
intersectVal
- The value of the node where the intersection occurs. This is0
if there is no intersected node.listA
- The first linked list.listB
- The second linked list.skipA
- The number of nodes to skip ahead inlistA
(starting from the head) to get to the intersected node.skipB
- The number of nodes to skip ahead inlistB
(starting from the head) to get to the intersected node.The judge will then create the linked structure based on these inputs and pass the two heads,
headA
andheadB
to your program. If you correctly return the intersected node, then your solution will be accepted.
解题思路:
因为题目希望最好space complexityO(1)。所以还是只能用双指针。
本来我的想法是如果有intersection point的话,那么长短链的尾部一部分是重合的,可以把两个指针放在长短链的最后,往回走,走到不再相同为止的上一个点就是intersection。但是因为这个是单链,所以这样行不通。
参考了solution的解法后,可以把双指针长短链先后走一遍,就会同时到达intersection point。喵喵喵。
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> Optional[ListNode]:
pt1 = headA
pt2 = headB
end1 = end2 = 0
while pt1 and pt2:
if pt1 == pt2:
return pt1
pt1 = pt1.next
if pt1 == None and end1 == 0 :
pt1 = headB
end1 = 1
pt2 = pt2.next
if pt2 == None and end2 == 0:
pt2 = headA
end2 = 1
return None
长链走完马上重新回到短链,所以设置了指针一旦触尾,即None,马上掉头。但是第二次触尾就该终止while循环了。因此设置了end1和end2关卡。
runtime:
forum里的解法:
class Solution:
# @param two ListNodes
# @return the intersected ListNode
def getIntersectionNode(self, headA, headB):
if headA is None or headB is None:
return None
pa = headA # 2 pointers
pb = headB
while pa is not pb:
# if either pointer hits the end, switch head and continue the second traversal,
# if not hit the end, just move on to next
pa = headB if pa is None else pa.next
pb = headA if pb is None else pb.next
return pa # only 2 ways to get out of the loop, they meet or the both hit the end=None
# the idea is if you switch head, the possible difference between length would be countered.
# On the second traversal, they either hit or miss.
# if they meet, pa or pb would be the node we are looking for,
# if they didn't meet, they will hit the end at the same iteration, pa == pb == None, return either one of them is the same,None
while循环设置的结束条件是两个指针相等。
我没有想到的是即使不存在intersection point的点,长短链都跑一遍,最后指针会同时触尾,即None。这个时候随便输出任一指针,都是None。
确实这样比我的解法更简洁。学到了。