https://leetcode.com/problems/intersection-of-two-linked-lists/#/description
Write a program to find the node at which the intersection of two singly linked lists begins.
For example, the following two linked lists:
A: a1 → a2 ↘ c1 → c2 → c3 ↗ B: b1 → b2 → b3
begin to intersect at node c1.
Notes:
- If the two linked lists have no intersection at all, return
null
. - The linked lists must retain their original structure after the function returns.
- You may assume there are no cycles anywhere in the entire linked structure.
- Your code should preferably run in O(n) time and use only O(1) memory.
Sol 1:
The key point is to find the overlap node, and when node A is not equal to node B, advance them and when either of them reaches the end, switch the head and continue the second traversal. There are two ways to get out the while A != B list :1) They meet. 2) They both hit the end = None.
(similar to the check loop in linked list)
# Definition for singly-linked list. class ListNode(object): def __init__(self, x): self.val = x self.next = None class Solution(object): def getIntersectionNode(self, headA, headB): """ :type head1, head1: ListNode :rtype: ListNode """ if (not headA) or (not headB): return None if headA and headB: A = headA B = headB while A != B: # if either pointer hits the end, switch head and continue the second traversal, # if not hit the end, just move on to next if A: A = A.next else: A = headB if B: B = B.next else: B = headA return A # 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
Sol 2:
Traverse list A and list B once to get the length of list A and list B. Then reset current nodes as headA an headB. Advance the pointer on the longer list. While current A is not equal to current B, advance both list A and list B pointer, and after the while loop, we find the intersection where current node A equals to current node B, then return current A.
O(n) time and O(1) space
# Definition for singly-linked list. class ListNode(object): def __init__(self, x): self.val = x self.next = None class Solution(object): def getIntersectionNode(self, headA, headB): """ :type head1, head1: ListNode :rtype: ListNode """ curA = headA curB = headB lenA = 0 lenB = 0 while curA: lenA += 1 curA = curA.next while curB: lenB += 1 curB = curB.next curA = headA curB = headB if lenA > lenB: for i in range(lenA - lenB): curA = curA.next elif lenB > lenA: for i in range(lenB - lenA): curB = curB.next while curB != curA: curB = curB.next curA = curA.next return curA
Sol 3:
This problem could be considered as the derivation of linked list cycle.
Let say there are two linked lists named l1 and l2. And h1 and t1 are the head and last nodes of l1 respectively, and h2 is the head node of l2.
- Concat h1 and t1
- Check whether there exists a cycle of linked list l2.
- Find that intersection if 2 is a truth.
Before doing the above steps, there are two linked lists in the picture:
Then let's try to make the linked lists easier to understood.
Node 8 is what we want. We can use then solve it by finding the start node of the cycle like the problem "linked list cycle II"
def getIntersectionNode(self, headA, headB): """ :type head1, head1: ListNode :rtype: ListNode """ if not headA or not headB: return None p = headA while p.next: p = p.next mark = p #make a cycled list mark.next = headA rst = None p1 = headB p2 = headB while p1 and p2: p1 = p1.next p2 = p2.next if p2: p2 = p2.next if p1 == p2: break if p1 and p2 and p1 == p2: p1 = headB while p1 != p2: p1 = p1.next p2 = p2.next rst = p1 #unmake the cycle mark.next = None
return rst