Problem Statement
Given the heads of two linked lists A and B. The task is to return the node where both the linked lists intersect. If there is no point of intersection, return NULL.
Examples:
Input:
Output: Node 8
Explanation: Shown in image
Confused about your next job?
Approach 1: Brute Force
A simple approach is to, traverse every node of the linked list B, for each node of A and simply check if any of the nodes is present in the list B.
C++ Code
ListNode * getIntersectionNode(ListNode * headA, ListNode * headB) { while (headA != nullptr) { ListNode * pB = headB; while (pB != nullptr) { if (headA == pB) return headA; pB = pB -> next; } headA = headA -> next; } return nullptr; }
Java Code
public ListNode getIntersectionNode(ListNode headA, ListNode headB) { while (headA != null) { ListNode pB = headB; while (pB != null) { if (headA == pB) return headA; pB = pB.next; } headA = headA.next; } return null; }
Python Code
def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode: while headA is not None: pB = headB while pB is not None: if headA == pB: return headA pB = pB.next headA = headA.next return None
Time Complexity:O(N * M), where N and M is the size of the linked lists
Space Complexity:O(1), as no extra space is used.
Approach 2: Hashing
In the previous approach, instead of traversing through all the nodes of B, we can simply keep track of a hashmap that stores each node of B. Now simply traverse list A, and check if any of the nodes is already present in the hashmap. If true, then it is the intersection point.
Algorithm
- Initialise a hashmap of nodes.
- Traverse the list B and store each node address into the hashmap.
- Traverse the array A and if the current node is already present in the hashmap, then it is the intersection point, else continue traversing.
- If list A is exhausted, there is no intersection point. Hence, return NULL.
C++ Implementation
ListNode * getIntersectionNode(ListNode * headA, ListNode * headB) { set < ListNode * > nodes_in_B; while (headB != nullptr) { nodes_in_B.insert(headB); headB = headB -> next; } while (headA != nullptr) { if (nodes_in_B.find(headA) != nodes_in_B.end()) { return headA; } headA = headA -> next; } return nullptr; }
Java Implementation
public ListNode getIntersectionNode(ListNode headA, ListNode headB) { Set < ListNode > nodesInB = new HashSet < ListNode > (); while (headB != null) { nodesInB.add(headB); headB = headB.next; } while (headA != null) { if (nodesInB.contains(headA)) { return headA; } headA = headA.next; } return null; }
Python Implementation
def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode: nodes_in_B = set() while headB is not None: nodes_in_B.add(headB) headB = headB.next while headA is not None: if headA in nodes_in_B: return headA headA = headA.next return None
Time Complexity:O(N + M), where N and M is the size of the linked list
Space Complexity:O(M), since the nodes of list B are stored.
Approach 3: Two Pointers
While we have already achieved the best time complexity possible, but is it possible to reduce the space complexity?
Well, it can be done in O(1) using a two-pointer approach. Let’s understand how.
The key idea to note is that, if the two linked lists contain a common point, the length from that intersection point to the tail will be the same.
Since the tail length must be the same, the intersection node should be any of the first five nodes in the given image.
Therefore, place two-pointers and keep checking if the nodes are equal.
Algorithm
- Set a pointer p1 to list A.
- Set a pointer p2 to list B.
- Run a while loop and while the nodes pointed by p1 and p2 are not same:
- If p1 is pointing to NULL, set p1 to head of B.
- Else, move to the next node of A.
- If p2 is pointing to NULL, set p2 to head of A.
- Else, move to the next node of B.
- Return the node pointed by p1.
C++ Code For Two Pointers Approach
ListNode * getIntersectionNode(ListNode * headA, ListNode * headB) { ListNode * pA = headA; ListNode * pB = headB; while (pA != pB) { pA = pA == nullptr ? headB : pA -> next; pB = pB == nullptr ? headA : pB -> next; } return pA; }
Java Code For Two Pointers Approach
public ListNode getIntersectionNode(ListNode headA, ListNode headB) { ListNode pA = headA; ListNode pB = headB; while (pA != pB) { pA = pA == null ? headB : pA.next; pB = pB == null ? headA : pB.next; } return pA; }
Python Code For Two Pointers Approach
def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode: pA = headA pB = headB while pA != pB: pA = headB if pA is None else pA.next pB = headA if pB is None else pB.next return pA
Time Complexity:O(N + M), where N and M is the size of the linked list
Space Complexity:O(1), since no extra space is used.