Bird
Raised Fist0
DSA Typescriptprogramming~15 mins

Intersection Point of Two Linked Lists in DSA Typescript - Deep Dive

Choose your learning style10 modes available
Overview - Intersection Point of Two Linked Lists
What is it?
Given two singly linked lists that may share a common tail, find the node where they first merge. Intersection means the same object reference — both pointers hold the exact same ListNode instance in memory. In TypeScript, object reference equality is checked with === which compares references (memory addresses), not the values of the properties.
Why it matters
TypeScript inherits JavaScript's reference semantics for objects — understanding when === means value equality (primitives) vs reference equality (objects) is essential for correct data structure manipulation. The two-pointer path-swap technique demonstrates O(1) space intersection detection without any extra data structures.
Where it fits
You need comfort with TypeScript class references, linked list traversal, and === semantics for objects before tackling this. After mastering it, Floyd's cycle detection, merging sorted lists, and WeakMap-based caching follow naturally.
Mental Model
Core Idea
Two runners covering the same total distance by switching paths will meet exactly at the shared section — regardless of starting path.
Think of it like...
Two roads of different lengths merge onto one shared highway. Driver A takes road A then road B; driver B takes road B then road A. Both travel the same total distance and enter the merged highway simultaneously.
List A:  1 → 3 → 5 ─┐
                       ├→ 8 → 10 → null
List B:  2 → 4 ─────┘

pA: 1→3→5→8→10→null → 2→4→[8] ✓
pB: 2→4→8→10→null → 1→3→5→[8] ✓
Both reach the same ListNode object {val:8} simultaneously.
Build-Up - 6 Steps
1
FoundationReference Equality in TypeScript — === on Objects
🤔
Concept: === on objects compares references (memory addresses), not property values.
TypeScript compiles to JavaScript and inherits its reference semantics. For objects, nodeA === nodeB is true only when both variables reference the same object in memory. Two separate objects { val: 8, next: null } and { val: 8, next: null } are NOT === even if their properties are identical. TypeScript's type system adds compile-time safety but does not change runtime reference semantics. Use === for intersection detection — never compare .val.
Result
=== on ListNode objects is always reference comparison — the correct intersection check.
TypeScript's strict mode and type annotations help catch type errors at compile time, but reference equality behavior at runtime is pure JavaScript.
2
FoundationBrute Force — O(m×n) Nested Loop
🤔
Concept: For every node in list A, scan all of list B checking reference equality.
Outer loop traverses list A. Inner loop traverses list B. If pA === pB (same reference), return that node. Time O(m×n), space O(1). Confirms === is the correct check before optimizing.
Result
Correct baseline establishing === as the intersection check.
Brute force verifies the mental model: shared object reference = intersection. No custom comparator needed.
3
IntermediateLength Difference Approach
🤔Before reading on: if list A has 6 nodes and list B has 4, how many steps should the longer pointer advance before syncing? Commit to your answer.
Concept: Count lengths, advance the longer pointer by the difference, then walk both in sync.
Count lenA and lenB. If lenA > lenB, advance pA by (lenA - lenB) steps. Both are now equidistant from null. Walk both one step per iteration. First node where pA === pB is the intersection. Time O(m+n), space O(1).
Result
Efficient O(m+n) solution after tail alignment.
Once equidistant from null, the first common reference must be the intersection.
4
IntermediateTwo-Pointer Path-Swap Technique
🤔Before reading on: if pA traverses list A then list B, and pB traverses list B then list A, do both cover the same total node count? Commit yes or no.
Concept: When a pointer reaches null, redirect it to the head of the other list.
Initialize pA = headA, pB = headB. Each step advance both. When pA === null, set pA = headB. When pB === null, set pB = headA. Continue until pA === pB. In TypeScript: while (pA !== pB) { pA = pA !== null ? pA.next : headB; pB = pB !== null ? pB.next : headA; } return pA;
Result
Elegant O(m+n) time, O(1) space with no length variables.
lenA + lenB === lenB + lenA. The path swap exploits this arithmetic symmetry to cancel the starting offset.
5
Advancednull === null in TypeScript/JavaScript
🤔Before reading on: does null === null evaluate to true in TypeScript? Commit yes or no.
Concept: Both pointers become null simultaneously when no intersection exists, cleanly terminating the loop.
If no intersection exists, after traversing both lists, pA === null and pB === null simultaneously. null === null is true in TypeScript (null is a primitive value). So pA !== pB evaluates to false and the while loop exits cleanly. Return null (or pA, which is null).
Result
Same loop handles both intersecting and non-intersecting cases without special casing.
TypeScript's strict null checks (strictNullChecks) require handling null explicitly — use ListNode | null as the return type for correctness.
6
ExpertSet Approach — TypeScript Set<ListNode>
🤔Before reading on: does JavaScript/TypeScript Set use reference equality for object membership? Commit yes or no.
Concept: Store all node references from list A in a Set, then scan list B.
const visited = new Set(). Traverse list A: visited.add(node). Traverse list B: first node where visited.has(node) is true is the intersection. Set.has() uses the SameValueZero algorithm — reference equality for objects. Time O(m+n), space O(m). TypeScript's generic Set adds type safety without affecting runtime behavior.
Result
Correct O(m+n) solution at O(m) space — simpler implementation than two-pointer.
TypeScript's Set is a thin type wrapper over JavaScript's Set — same reference-based membership semantics, with compile-time type checking.
Under the Hood
The path-swap works because pA travels lenA + lenB nodes and pB travels lenB + lenA — identical totals. If intersection exists at distance d from null, both arrive at that object reference after lenA + lenB - d steps. The different starting positions cancel exactly through the path exchange.
Why designed this way?
TypeScript's type system (interfaces, generics, strict null checks) adds compile-time safety but doesn't change runtime memory or reference semantics. The algorithm is identical to JavaScript — only the type annotations and strictNullChecks handling differ. Using ListNode | null instead of ListNode? makes null handling explicit and type-safe.
TypeScript type-safe implementation:

function getIntersectionNode(
  headA: ListNode | null,
  headB: ListNode | null
): ListNode | null {
  let pA: ListNode | null = headA;
  let pB: ListNode | null = headB;
  while (pA !== pB) {
    pA = pA !== null ? pA.next : headB;
    pB = pB !== null ? pB.next : headA;
  }
  return pA; // null if no intersection, node if intersection
}
Myth Busters - 3 Common Misconceptions
Quick: does pA.val === pB.val confirm intersection in TypeScript? Commit yes or no.
Common Belief:Two nodes intersect if their val properties are equal.
Tap to reveal reality
Reality:Intersection requires pA === pB (same reference). Two distinct objects with identical val are not the same node.
Why it matters:val comparison produces false positives on lists with duplicate values — a silent TypeScript bug that the type system cannot catch.
Quick: does TypeScript's strict mode change === behavior for objects? Commit yes or no.
Common Belief:TypeScript strict mode makes === compare property values for objects.
Tap to reveal reality
Reality:TypeScript strict mode only affects type checking at compile time. Runtime === always compares references for objects — no TypeScript option changes this.
Why it matters:Confusing TypeScript's type strictness with runtime equality semantics leads to incorrect assumptions about how === works on objects.
Quick: does Set.has() perform deep equality check in TypeScript? Commit yes or no.
Common Belief:Set.has() compares all properties of ListNode for equality.
Tap to reveal reality
Reality:Set uses SameValueZero (effectively ===) for object membership — reference identity, not deep equality. TypeScript's generic type parameter does not affect this.
Why it matters:Expecting deep equality from Set leads to incorrect intersection detection — the Set correctly uses reference identity by default.
Expert Zone
1
TypeScript's strictNullChecks forces explicit null handling. Without it, null and undefined can silently slip through — strict mode is recommended for linked list problems.
2
The path-swap requires exactly one redirect per pointer. TypeScript's conditional type checking at compile time cannot verify this constraint — it must be reasoned about algorithmically.
3
WeakMap can replace Set for the visited approach — WeakMap holds weak references, allowing garbage collection of nodes that are no longer reachable from list heads.
When NOT to use
If lists may contain cycles, pointers never reach null and the redirect never fires. Detect and break cycles first. If using value objects (plain data without shared references), === will always be false — use a Map keyed by a unique identifier property instead.
Production Patterns
Reference intersection detection appears in React's reconciliation (detecting shared component instances), TypeScript AST analysis (shared node detection in the compiler), and graph algorithm libraries. The path-swap generalizes to any two-sequence synchronization where a shared suffix must be located efficiently.
Connections
Floyd's Cycle Detection in TypeScript
Both use two-pointer synchronization with mathematically guaranteed meeting points, operating on reference comparisons.
Mastering intersection detection makes Floyd's algorithm in TypeScript intuitive — same === comparison, different pointer movement rules.
TypeScript Reference vs Value Semantics
=== for primitives (number, string, boolean) compares values; for objects it compares references. This problem is a practical drill on the object side of this distinction.
This distinction is the foundation for understanding React's useMemo/useCallback (reference equality triggers), Redux state management (reference equality for change detection), and TypeScript's type narrowing.
Common Pitfalls
#1Comparing .val instead of object references.
Wrong approach:while (pA !== null && pB !== null) { if (pA.val === pB.val) return pA; // WRONG pA = pA.next; pB = pB.next; }
Correct approach:while (pA !== pB) { pA = pA !== null ? pA.next : headB; pB = pB !== null ? pB.next : headA; } return pA; // Correct reference comparison
Root cause:=== on objects compares references, not property values. pA.val === pB.val compares numbers — a completely different check.
#2TypeScript strictNullChecks causes compile error on unguarded null access.
Wrong approach:// TypeScript error: Object is possibly 'null' pA = pA.next; // ERROR if pA could be null
Correct approach:// Guard null before accessing .next pA = pA !== null ? pA.next : headB; // OR use non-null assertion (only when certain) pA = pA!.next;
Root cause:TypeScript's strictNullChecks enforces null safety at compile time. The ternary null guard is the correct approach — it's also the redirect logic needed by the algorithm.
Key Takeaways
Intersection means the same object reference (pA === pB) — never compare .val for intersection detection.
TypeScript's === on objects is always reference equality — strict mode does not change this runtime behavior.
null === null is true in TypeScript — both pointers reaching null simultaneously terminates the loop cleanly.
Set.has() uses reference identity by default — no custom comparator needed.
Use ListNode | null as return type with strictNullChecks for type-safe intersection detection.

Practice

(1/5)
1. What does the "Intersection Point of Two Linked Lists" problem ask you to find?
easy
A. The node where two linked lists merge or intersect
B. The sum of all nodes in both linked lists
C. The length of the longer linked list
D. The first node of the longer linked list

Solution

  1. Step 1: Understand the problem goal

    The problem asks to find the node where two linked lists join or share the same reference, not just the value.
  2. Step 2: Clarify what intersection means

    Intersection means the exact same node object, not just nodes with equal values.
  3. Final Answer:

    The node where two linked lists merge or intersect -> Option A
  4. Quick Check:

    Intersection point = node shared by both lists [OK]
Hint: Look for the shared node reference, not just values [OK]
Common Mistakes:
  • Confusing intersection with nodes having same values
  • Thinking intersection means equal length lists
  • Looking for sum or length instead of node
2. Which TypeScript syntax correctly declares a singly linked list node class for this problem?
easy
A. type ListNode = { val: number; next: ListNode | undefined }
B. function ListNode(val) { this.val = val; this.next = null; }
C. interface ListNode { val: number; next: ListNode; }
D. class ListNode { val: number; next: ListNode | null; constructor(val: number) { this.val = val; this.next = null; } }

Solution

  1. Step 1: Check for class declaration with constructor

    class ListNode { val: number; next: ListNode | null; constructor(val: number) { this.val = val; this.next = null; } } correctly defines a class with a constructor initializing val and next properties.
  2. Step 2: Verify type safety and nullability

    class ListNode { val: number; next: ListNode | null; constructor(val: number) { this.val = val; this.next = null; } } uses 'next: ListNode | null' which is correct for linked list end.
  3. Final Answer:

    class ListNode { val: number; next: ListNode | null; constructor(val: number) { this.val = val; this.next = null; } } -> Option D
  4. Quick Check:

    Proper class with constructor and nullable next [OK]
Hint: Use class with constructor and nullable next for nodes [OK]
Common Mistakes:
  • Using interface without constructor
  • Missing null for next pointer
  • Using function syntax without types
3. Given the following TypeScript code, what will be the output printed?
class ListNode {
  val: number;
  next: ListNode | null;
  constructor(val: number) {
    this.val = val;
    this.next = null;
  }
}

function getIntersectionNode(headA: ListNode | null, headB: ListNode | null): ListNode | null {
  let pA = headA;
  let pB = headB;
  while (pA !== pB) {
    pA = pA ? pA.next : headB;
    pB = pB ? pB.next : headA;
  }
  return pA;
}

// Create nodes
const common = new ListNode(8);
common.next = new ListNode(10);

const listA = new ListNode(3);
listA.next = new ListNode(7);
listA.next.next = common;

const listB = new ListNode(99);
listB.next = common;

const intersection = getIntersectionNode(listA, listB);
console.log(intersection ? intersection.val : null);
medium
A. 7
B. 10
C. 8
D. null

Solution

  1. Step 1: Trace the linked lists and intersection node

    List A: 3 -> 7 -> 8 -> 10; List B: 99 -> 8 -> 10; common intersection starts at node with value 8.
  2. Step 2: Understand the two-pointer approach

    Pointers pA and pB traverse each list; when one reaches end, it switches to the other list's head. They meet at intersection node 8.
  3. Final Answer:

    8 -> Option C
  4. Quick Check:

    Intersection node value = 8 [OK]
Hint: Two pointers meet at intersection or null if none [OK]
Common Mistakes:
  • Returning node value 7 or 10 instead of 8
  • Confusing node values with references
  • Not switching pointers to other list head
4. Identify the bug in this TypeScript function to find the intersection point of two linked lists:
function getIntersectionNode(headA: ListNode | null, headB: ListNode | null): ListNode | null {
  let pA = headA;
  let pB = headB;
  while (pA !== pB) {
    pA = pA.next;
    pB = pB.next;
    if (!pA && !pB) return null;
  }
  return pA;
}
medium
A. Pointers do not switch to the other list's head after reaching null
B. The function returns null too early when both pointers are null
C. The while loop condition should be pA == pB instead of !==
D. The function does not handle empty lists

Solution

  1. Step 1: Analyze pointer movement in the loop

    Both pointers move forward but do not switch to the other list's head when reaching null, so they may never meet.
  2. Step 2: Understand the standard approach

    To find intersection, pointers must switch to the other list's head after reaching null to align lengths.
  3. Final Answer:

    Pointers do not switch to the other list's head after reaching null -> Option A
  4. Quick Check:

    Switch pointers to other list head to find intersection [OK]
Hint: Switch pointers to other list head on null to align [OK]
Common Mistakes:
  • Not switching pointers causes infinite loop or wrong result
  • Returning null too early without full traversal
  • Incorrect loop condition
5. You have two singly linked lists that intersect at some node. List A has length 7, List B has length 5, and they share the last 3 nodes. Which approach correctly finds the intersection point efficiently?
hard
A. Traverse both lists fully and compare node values at each step
B. Calculate lengths, advance longer list by difference, then move both pointers together
C. Reverse both lists and compare from the start
D. Use a hash set to store all nodes of the shorter list and check nodes of the longer list

Solution

  1. Step 1: Calculate lengths and difference

    List A length = 7, List B length = 5, difference = 2.
  2. Step 2: Advance longer list pointer by difference

    Move pointer in List A forward by 2 nodes to align with List B pointer.
  3. Step 3: Move both pointers together to find intersection

    Advance both pointers step-by-step until they meet at the intersection node.
  4. Final Answer:

    Calculate lengths, advance longer list by difference, then move both pointers together -> Option B
  5. Quick Check:

    Align pointers by length difference to find intersection [OK]
Hint: Advance longer list by length difference before simultaneous traversal [OK]
Common Mistakes:
  • Comparing node values instead of references
  • Reversing lists wastes time and breaks structure
  • Using hash set wastes extra space unnecessarily
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard