Common linked list patterns (runner technique) in Data Structures Theory - Time & Space Complexity
When working with linked lists, the runner technique helps us move through the list efficiently.
We want to know how the time needed changes as the list gets longer.
Analyze the time complexity of the following code snippet.
Node* slow = head;
Node* fast = head;
while (fast != nullptr && fast->next != nullptr) {
slow = slow->next;
fast = fast->next->next;
}
// slow now points to the middle node
This code uses two pointers moving at different speeds to find the middle of a linked list.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Moving the fast and slow pointers through the list.
- How many times: The loop runs about half the length of the list because fast moves two steps each time.
As the list gets longer, the loop runs more times, but only about half as many as the list length.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | 5 |
| 100 | 50 |
| 1000 | 500 |
Pattern observation: The number of steps grows roughly in direct proportion to the list size.
Time Complexity: O(n)
This means the time to find the middle grows linearly as the list gets longer.
[X] Wrong: "Because the fast pointer moves two steps, the time complexity is O(n/2), which is faster than O(n)."
[OK] Correct: We ignore constants in time complexity, so O(n/2) is the same as O(n). The time still grows linearly with input size.
Understanding the runner technique shows you can handle linked lists efficiently, a common skill interviewers look for.
"What if the fast pointer moved three steps at a time instead of two? How would the time complexity change?"
Practice
runner technique in linked lists?Solution
Step 1: Understand the runner technique concept
The runner technique involves two pointers moving through the list at different speeds to solve problems like finding the middle or detecting loops.Step 2: Identify the main purpose
This technique is used to efficiently solve linked list problems in one pass without extra memory.Final Answer:
To use two pointers moving at different speeds to solve problems efficiently -> Option AQuick Check:
Runner technique = two pointers at different speeds [OK]
- Thinking it sorts the list
- Confusing it with list conversion
- Assuming it deletes nodes
Solution
Step 1: Understand pointer initialization for runner technique
Typically, slow pointer starts at head, and fast pointer starts at the next node to move faster.Step 2: Check each option
slow = head; fast = head.next correctly sets slow to head and fast to head.next, allowing fast to move two steps ahead.Final Answer:
slow = head; fast = head.next -> Option BQuick Check:
Fast pointer starts one step ahead [OK]
- Setting slow ahead of fast
- Starting pointers at null
- Both pointers starting at same node without offset
Using the runner technique where
slow moves one step and fast moves two steps, what value will slow point to when fast reaches the end?Solution
Step 1: Trace slow and fast pointers through the list
Start: slow=1, fast=1
Move 1: slow=2, fast=3
Move 2: slow=3, fast=5
Move 3: fast tries to move two steps but reaches null, stop.Step 2: Identify slow pointer's position when fast ends
When fast reaches the end (node 5), slow is at node 3.Final Answer:
3 -> Option DQuick Check:
Middle node = 3 [OK]
- Stopping too early and picking 2
- Assuming slow moves as fast as fast pointer
- Confusing node values with pointer positions
Solution
Step 1: Understand the role of fast pointer speed
The fast pointer moves two steps to catch up or reach the end faster than slow pointer.Step 2: Analyze effect if fast moves only one step
If fast moves one step, both pointers move at same speed, so fast never overtakes slow, possibly causing infinite loop in cycle detection.Final Answer:
The fast pointer will never reach the end, causing an infinite loop -> Option AQuick Check:
Fast pointer speed crucial to avoid infinite loops [OK]
- Assuming slow pointer moves too fast
- Thinking technique works with equal speeds
- Ignoring infinite loop possibility
Solution
Step 1: Recall cycle detection with runner technique
If a cycle exists, fast pointer will eventually catch up to slow pointer inside the loop.Step 2: Identify the condition for cycle detection
The pointers meeting at the same node means the list has a cycle.Final Answer:
The slow and fast pointers meet at the same node -> Option CQuick Check:
Pointers meeting = cycle detected [OK]
- Thinking fast pointer reaching null means cycle
- Assuming slow pointer reaches end means cycle
- Confusing pointer speeds
Ready to prove it?
Pass the test and this pattern moves unknown
