Intersection Point of Two Linked Lists in DSA Rust - Time & Space Complexity
We want to know how long it takes to find where two linked lists meet.
How does the time grow as the lists get longer?
Analyze the time complexity of the following code snippet.
fn get_intersection_node(head_a: Option<&Box>, head_b: Option<&Box>) -> Option<&Box> {
let mut a = head_a;
let mut b = head_b;
while a != b {
a = if a.is_none() { head_b } else { a.unwrap().next.as_ref() };
b = if b.is_none() { head_a } else { b.unwrap().next.as_ref() };
}
a
}
This code tries to find the node where two linked lists join by moving pointers through both lists.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Moving two pointers step-by-step through the lists.
- How many times: Each pointer moves at most twice the length of its list.
As the lists get longer, the pointers take more steps, but only up to the sum of both list lengths.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 20 steps |
| 100 | About 200 steps |
| 1000 | About 2000 steps |
Pattern observation: The steps grow roughly in a straight line with the total length of both lists combined.
Time Complexity: O(m + n)
This means the time grows linearly with the sum of the lengths of the two lists.
[X] Wrong: "The time is O(m * n) because we compare every node of one list with every node of the other."
[OK] Correct: The code uses two pointers moving through the lists, not nested loops, so it only takes steps proportional to the total length, not their product.
Understanding this time complexity helps you explain how efficient pointer techniques can solve problems without extra memory or slow nested loops.
"What if we changed the code to use nested loops comparing each node of one list to every node of the other? How would the time complexity change?"
Practice
intersection point mean in the context of two linked lists?Solution
Step 1: Understand linked list nodes
Each node in a linked list has a value and a reference (memory address) to the next node.Step 2: Define intersection point
The intersection point is where two linked lists share the exact same node reference, meaning they merge at that node.Final Answer:
The node where both linked lists share the same reference (memory address). -> Option CQuick Check:
Intersection means shared node reference [OK]
- Confusing same value with same node reference
- Thinking intersection is about list length
- Assuming intersection is always at the start
Solution
Step 1: Understand Rust linked list node
Rust needs Option<Box<Node>> for next to allow None and heap allocation.Step 2: Check each option
A uses raw Node causing infinite size error. C uses reference without lifetime. D lacks Option so cannot represent end of list. The correct declaration uses Option<Box<Node>>.Final Answer:
struct Node { value: i32, next: Option<Box<Node>> } -> Option AQuick Check:
Use Option<Box<Node>> for next pointer [OK]
- Omitting Option causing infinite size error
- Using references without lifetimes
- Using raw Node type causing recursive size
Solution
Step 1: Identify shared nodes
Lists share nodes with values 4 and 5, meaning intersection starts at node with value 4.Step 2: Determine intersection point
The first shared node is the intersection point, which is value 4.Final Answer:
4 -> Option AQuick Check:
First shared node value = 4 [OK]
- Choosing last shared node value
- Picking non-shared node values
- Confusing node value with node reference
fn get_intersection_node(head_a: Option<&Box<Node>>, head_b: Option<&Box<Node>>) -> Option<&Box<Node>> {
let mut a = head_a;
let mut b = head_b;
while a != b {
a = if let Some(node) = a { node.next.as_ref() } else { head_b };
b = if let Some(node) = b { node.next.as_ref() } else { head_a };
}
a
}
What is the main bug in this code?Solution
Step 1: Analyze compilation
The function uses bare references (&Box<Node>) in Option without lifetime parameters.Step 2: Rust lifetime rules
Explicit lifetime annotations are required (e.g., fn<'a>(head_a: Option<&'a Box<Node>>, ...) -> Option<&'a Box<Node>>), otherwise it fails to compile due to unresolved lifetimes.Final Answer:
It uses references without proper lifetime annotations causing compile error. -> Option DQuick Check:
Missing lifetime specifiers [OK]
- Assuming != compares pointers correctly
- Ignoring infinite loop possibility
- Overlooking lifetime errors
Solution
Step 1: Understand length difference method
Calculate difference in lengths (7 - 5 = 2), advance longer list by 2 nodes to align both lists.Step 2: Move both pointers together
Then move both pointers one step at a time until they point to the same node (intersection point).Final Answer:
Calculate length difference, advance longer list by difference, then move both pointers together. -> Option BQuick Check:
Align lists by length difference for efficient intersection [OK]
- Using extra memory unnecessarily
- Reversing lists which is inefficient
- Comparing node values instead of references
Ready to prove it?
Pass the test and this pattern moves unknown
