Loading problems...
TL;DR: The optimal solution uses two pointers traversing the concatenated length of both lists to neutralize length differences and locate the intersection node in time with space.
The Intersection of Two Linked Lists problem asks us to identify the specific node where two singly linked lists merge. If the lists intersect, they form a Y-shape, sharing all nodes after the intersection point. If they do not intersect, we must return . Importantly, the solution must retain the original structure of the lists, and the intersection is defined by reference (memory address), not by node value. This is a classic interview question that tests pointer manipulation skills.
nullThe naive approach involves checking every node in the first list against every node in the second list to see if they point to the same memory location.
headA with a pointer ptrA.ptrA, iterate through the entire list headB using ptrB.ptrA == ptrB (reference equality).null.Pseudo-code:
textfor nodeA in listA: for nodeB in listB: if nodeA is nodeB: return nodeA return null
Complexity Analysis: The time complexity is , where and are the lengths of the two lists. For large inputs (up to nodes each), this results in approximately operations, which is highly inefficient and may lead to a Time Limit Exceeded (TLE) error or simply fail the interview constraint of linear time complexity.
The fundamental challenge in LeetCode 160 is that the two lists may have different lengths before the intersection point. A pointer traversing the shorter list will reach the intersection sooner than a pointer traversing the longer list.
To solve this, we must synchronize the pointers so they arrive at the intersection simultaneously. The core insight is to virtually "concatenate" the lists.
If a pointer traverses List A and then immediately switches to the head of List B, the total distance it covers is Length(A) + Length(B). Conversely, a pointer traversing List B then List A covers Length(B) + Length(A). Since addition is commutative, both pointers traverse exactly the same total distance.
Visual Description:
Imagine two pointers, pA and pB.
pA moves through List A. When it hits the end (null), it jumps to the head of List B.pB moves through List B. When it hits the end (null), it jumps to the head of List A.null at the exact same step after the swap.
ptrA points to the first node of List A; ptrB points to the first node of List B.ptrA and ptrB refer to the same object. If yes, return ptrA.ptrA forward. If ptrA was at the last node of List A, move it to the first node of List B.ptrB forward. If ptrB was at the last node of List B, move it to the first node of List A.len(A) + len(B) nodes and reach null at the same time. The condition ptrA == ptrB (where both are null) satisfies the loop termination.null).Let be the length of List A, be the length of List B, and be the length of the shared suffix (intersection).
When ptrA traverses A then B, it travels nodes (unique A), then nodes (shared), then switches to B and travels nodes (unique B) before reaching the intersection again.
Total distance to intersection: .
When ptrB traverses B then A, it travels nodes (unique B), then nodes (shared), then switches to A and travels nodes (unique A) before reaching the intersection again.
Total distance to intersection: .
Since the distance to the intersection is identical for both pointers, and they move at the same speed (1 node/step), they are guaranteed to meet at the intersection node. If no intersection exists (), they both travel and meet at null.
cpp/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) { // If either head is null, there is no intersection if (!headA || !headB) return nullptr; ListNode *ptrA = headA; ListNode *ptrB = headB; // Traverse until the pointers meet (either at the intersection node or at null) while (ptrA != ptrB) { // If ptrA reaches the end of listA, switch to headB // Otherwise, move to the next node ptrA = (ptrA == nullptr) ? headB : ptrA->next; // If ptrB reaches the end of listB, switch to headA // Otherwise, move to the next node ptrB = (ptrB == nullptr) ? headA : ptrB->next; } // Return the intersection node or null return ptrA; } };
java/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { * val = x; * next = null; * } * } */ public class Solution { public ListNode getIntersectionNode(ListNode headA, ListNode headB) { // Boundary check if (headA == null || headB == null) return null; ListNode ptrA = headA; ListNode ptrB = headB; // Continue until they collide or both hit null while (ptrA != ptrB) { // Switch tracks at the end of the list ptrA = (ptrA == null) ? headB : ptrA.next; ptrB = (ptrB == null) ? headA : ptrB.next; } return ptrA; } }
python# 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]: if not headA or not headB: return None ptrA = headA ptrB = headB # Loop until pointers meet or both become None while ptrA != ptrB: # If ptrA reaches end of list A, redirect to head B ptrA = ptrA.next if ptrA else headB # If ptrB reaches end of list B, redirect to head A ptrB = ptrB.next if ptrB else headA return ptrA
ptrA and ptrB) regardless of the input size. We do not use any additional data structures like Hash Sets or Stacks.The Linked List - Intersection Detection pattern and the two-pointer synchronization technique are applicable to other problems:
Why does comparing node.val fail?
if ptrA.val == ptrB.val.1) but reside at different memory addresses.Why do I get an infinite loop?
null state correctly or switching pointers without advancing them.null simultaneously or the logic prevents them from advancing, the termination condition ptrA == ptrB is never met.Why can't I just use a Hash Set?
Set to store nodes from List A and checking List B.