Table of Contents
Problem Description
Given the head nodes headA and headB of two singly linked lists, determine whether they intersect (i.e., some node is shared by both linked lists). If they intersect, return the intersection node; otherwise, return null.
Input: headA = 4→1→8→4→5 headB = 5→6→1→8→4→5 ↑ intersectionOutput: node 8The two linked lists meet at node 8, after which they share the 4→5 portion.
Solution Approach
Problems with the brute-force approach
- Hash table approach: Traverse linked list A and store all nodes in a hash table; then traverse linked list B and check whether each node is in the hash table. Space O(n).
- Two-pointer alternating traversal approach: Space O(1), completed in a single traversal.
Two-pointer alternating traversal approach
Key observation: If the two linked lists have an intersection, then the nodes after the intersection are exactly the same. The two lists may have different lengths, but the total path length from each respective head node to the intersection and then to the end is fixed.
Core idea
Let two pointers start from A and B respectively:
- Pointer
pA: starts from the head of A, and after reaching the end, jumps to the head of B and continues - Pointer
pB: starts from the head of B, and after reaching the end, jumps to the head of A and continues
If an intersection exists, the total distance traveled by both pointers is equal (both are lenA + lenB), and they will meet at the intersection. If no intersection exists, both pointers will eventually reach null at the same time.
Mathematical proof
Let the length of linked list A be lenA = a + c (a is the part unique to A, c is the shared part), and the length of linked list B be lenB = b + c.
| Pointer | First segment | Second segment | Total distance | Reaches intersection |
|---|---|---|---|---|
| pA | a | c + b | a + c + b | Yes |
| pB | b | c + a | b + c + a | Yes |
The total distance traveled by both pointers is a + b + c, so they will reach the intersection at the same time (or reach null at the same time).
Algorithm steps
pA = headA,pB = headB- Loop condition:
while (pA != pB) pAmoves one step; ifpA == null, jump toheadBpBmoves one step; ifpB == null, jump toheadA- When the loop ends, return
pA(the intersection or null)
Code Implementation
#include <stdio.h>#include <stdlib.h>
typedef struct ListNode { int val; struct ListNode *next;} ListNode;
ListNode* getIntersectionNode(ListNode *headA, ListNode *headB) { if (!headA || !headB) return NULL;
ListNode *pA = headA; ListNode *pB = headB;
// Two pointers traverse alternately while (pA != pB) { pA = pA ? pA->next : headB; // pA finishes A then goes to B pB = pB ? pB->next : headA; // pB finishes B then goes to A }
// Meeting point: intersection or null return pA;}struct ListNode { int val; ListNode *next; ListNode(int x) : val(x), next(nullptr) {}};
class Solution {public: ListNode* getIntersectionNode(ListNode *headA, ListNode *headB) { if (!headA || !headB) return nullptr;
ListNode *pA = headA; ListNode *pB = headB;
// Two pointers traverse alternately while (pA != pB) { pA = pA ? pA->next : headB; // pA finishes A then goes to B pB = pB ? pB->next : headA; // pB finishes B then goes to A }
// Meeting point: intersection or nullptr return pA; }};class ListNode { constructor(val) { this.val = val; this.next = null; }}
function getIntersectionNode(headA, headB) { if (!headA || !headB) return null;
let pA = headA; let pB = headB;
// Two pointers traverse alternately while (pA !== pB) { pA = pA ? pA.next : headB; // pA finishes A then goes to B pB = pB ? pB.next : headA; // pB finishes B then goes to A }
// Meeting point: intersection or null return pA;}Illustrated Process
Case with an intersection
Linked list A: a1 → a2 ↘ c1 → c2 → c3 ↗Linked list B: b1 → b2 → b3pA path: a1 → a2 → c1 → c2 → c3 → b1 → b2 → b3 → ★c1pB path: b1 → b2 → b3 → c1 → c2 → c3 → a1 → a2 → ★c1
At ★ the two pointers meet, so c1 is the intersection point ✓Case without an intersection
Linked list A: 1 → 2 → 3Linked list B: 4 → 5pA path: 1 → 2 → 3 → 4 → 5 → nullpB path: 4 → 5 → 1 → 2 → 3 → null
★ Both pointers reach null at the same time ✓Complexity Analysis
| Dimension | Analysis |
|---|---|
| Time complexity | O(m + n) — each pointer walks m + n steps |
| Space complexity | O(1) — only two pointers are used |
Key Points
- “Walk the path you walked”: pA finishes its own list and then walks B, while pB finishes its own list and then walks A—this design lets the two pointers eliminate the length difference and reach the intersection at the same time
- Reach null at the same time: If there is no intersection, the two pointers will also reach null at the same time after traversing the same total length, and the loop ends naturally
- Cannot skip null midway: Some implementations say “jump when reaching null,” which is fine, because acyclic linked lists all end in null
- Difference from cycle detection: This problem assumes the linked lists are acyclic. If cycles are possible, cycle detection must be done first
Extended Thinking
- If the linked lists may contain cycles, how do we determine intersection? — This requires case-by-case discussion: both acyclic, one cyclic and one acyclic, both cyclic
- Is there a more intuitive solution? — You can first compute the length difference between the two linked lists, let the pointer of the longer list walk the “difference” steps first, and then walk in sync
Related articles:
- Detect a cycle and find its starting point — another “meeting” logic
- Find the Kth node from the end — a similar idea of “eliminating the length difference”