Paths Subjects Questions Quizzes Pricing Search
Intermediate Open Free

Linked List Intersection

You are given the heads of two singly linked lists, headA and headB. The two lists may converge into a shared tail (i.e., after some point, the same physical nodes are shared by both lists), or they may not intersect at all. Return the node at which the two lists intersect, or None if they do not intersect. Intersection is defined by node identity (the same node object), not by equal values.

A:  a1 -> a2
              \
                c1 -> c2 -> c3 -> None
              /
B:  b1 -> b2 -> b3

Here headA and headB intersect at node c1.

Example 1

A: 4 -> 1 -\
             8 -> 4 -> 5 -> None
B:      5 -> 6 -> 1 -/
Output: node with value 8 (the intersection node)

Example 2

A: 1 -> 2 -> None
B: 3 -> 4 -> None
Output: None (no intersection)

Constraints

  • Combined node count across both lists is at most 3 * 10^4.
  • The lists themselves are guaranteed to be acyclic (no cycles).
  • Aim for O(n + m) time and O(1) extra space — do not use extra data structures like a hash set of visited nodes.
Solution

If the lists intersect, they share the exact same tail from the intersection point onward, but they can differ in length before that point. A hash-set-of-visited-nodes approach solves this in O(n + m) time but O(n) space; the O(1)-space trick is a clever pointer-swap.

Walk two pointers, one starting at headA and one at headB. When a pointer reaches the end of its own list, redirect it to the head of the other list instead of stopping. Because len(A) + len(B) is the same regardless of which list you started from, both pointers will have traveled the same total distance by the time they either meet at the intersection node or both become None simultaneously (no intersection).

class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

def get_intersection_node(
    headA: ListNode | None, headB: ListNode | None
) -> ListNode | None:
    if headA is None or headB is None:
        return None

    ptr_a, ptr_b = headA, headB
    while ptr_a is not ptr_b:
        ptr_a = ptr_a.next if ptr_a is not None else headB
        ptr_b = ptr_b.next if ptr_b is not None else headA

    return ptr_a  # either the intersection node, or None

Why it works: if the lists intersect, both pointers traverse len(A) + len(B) - len(shared tail) nodes before landing on the intersection node together. If they don't intersect, both pointers independently traverse len(A) + len(B) nodes and land on None together, ending the loop with ptr_a is ptr_b is None.

Complexity: O(n + m) time, where n and m are the two list lengths — each pointer traverses at most both lists once. O(1) extra space, since only two pointer variables are used.

Share this question

← Back to Linked Lists practice

We use cookies for product analytics to improve OmniAtlas. See our Privacy Policy.