0160 Intersection of Two Linked List#
Problem#
Given the heads of two singly linked-lists headA
and headB
, return the node at which the two lists intersect. If the two linked lists have no intersection at all, return null
.
For example, the following two linked lists begin to intersect at node c1
:
Examples#
Example 1:
Input: intersectVal = 8, listA = [4,1,8,4,5], listB = [5,6,1,8,4,5], skipA = 2, skipB = 3
Output: Intersected at '8'
Explanation: The intersected node's value is 8 (note that this must not be 0 if the two lists intersect).
From the head of A, it reads as [4,1,8,4,5]. From the head of B, it reads as [5,6,1,8,4,5]. There are 2 nodes before the intersected node in A; There are 3 nodes before the intersected node in B.
- Note that the intersected node's value is not 1 because the nodes with value 1 in A and B (2nd node in A and 3rd node in B) are different node references. In other words, they point to two different locations in memory, while the nodes with value 8 in A and B (3rd node in A and 4th node in B) point to the same location in memory.
Example 2:
Input: intersectVal = 2, listA = [1,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1
Output: Intersected at '2'
Explanation: The intersected node's value is 2 (note that this must not be 0 if the two lists intersect).
From the head of A, it reads as [1,9,1,2,4]. From the head of B, it reads as [3,2,4]. There are 3 nodes before the intersected node in A; There are 1 node before the intersected node in B.
Example 3:
Input: intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2
Output: No intersection
Explanation: From the head of A, it reads as [2,6,4]. From the head of B, it reads as [1,5]. Since the two lists do not intersect, intersectVal must be 0, while skipA and skipB can be arbitrary values.
Explanation: The two lists do not intersect, so return null.
Constraints#
The number of nodes of listA is in the m.
The number of nodes of listB is in the n.
1 <= m, n <= 3 * 104
1 <= Node.val <= 105
0 <= skipA < m
0 <= skipB < n
intersectVal is 0 if listA and listB do not intersect.
intersectVal == listA[skipA] == listB[skipB] if listA and listB intersect.
Analysis#
Method 1: hash map
create an empty hash set
traverse the first linked list, and store the visited node in the hash set
traverse the second linked list. Check if it is present in the hash set.
This method might requires all nodes have unique value. The example 2 probably will not pass.
Merhod 2: two pointer method
if two pointers
p1
andp2
walks normally on two lists, they cannot meet each other at the intersection. Then how can the two pointers can meet at the intersection?we can link these two lists together
traverse list 1, and then traverse list 2
traverse list 2, and then traverse list 1
if there is an intersection, the two pointers will have the same node
The idea can be described as the following figure.
Method 3: two pointer method
in cycle detection, we have algorithms to detect the cycle entrance, which is similar to intersection dectection
we can formulate a cycle out of these two intersected lists
make list 1 a circular list by connecting its last node to its first node -> make a cycle
detect the cycle entrance starting from the head of list 2
remove the circular list
Solution#
class Node():
def __init__(self, val=0, next=None):
self.val = val
self.next = next
def build(A):
dummy = Node()
if not A:
return dummy.next
prev = dummy
for a in A:
cur = Node(a)
prev.next = cur
prev = cur
return dummy.next
def linkedListToList(head):
res = []
while head:
res.append(head.val)
head = head.next
return res
# Method 2:
# Note current implementation will return None because when we build the linked list, the address are different for the nodes that are even intersected.
# The code will run on leetcode test
def intersectionList(headA, headB):
p1, p2 = headA, headB
while p1 != p2:
if p1 == None:
p1 = headB
else:
p1 = p1.next
if p2 == None:
p2 = headA
else:
p2 = p2.next
if not p1:
return None
return p1
# Test
headA = build([[4,1,8,4,5]])
headB = build([[5,6,1,8,4,5]])
print(intersectionList(headA, headB))
None
# Method 3:
def intersectionList(headA, headB):
# formulate a cycle
tailA = headA
while tailA.next:
tailA = tailA.next
tailA.next = headA
# detect the cycle entrance and return
slow, fast = headB, headB
while fast and fast.next:
slow = slow.next
fast = fast.next.next
if slow == fast:
break
# find entrance if there is cycle
if fast and fast.next:
slow = headB
while slow != fast:
slow = slow.next
fast = fast.next
return slow
# return None if no cycle
else:
return None