Traversal of Circular Linked List in DSA Rust - Time & Space Complexity
We want to understand how long it takes to visit every item in a circular linked list.
How does the time grow as the list gets bigger?
Analyze the time complexity of the following code snippet.
struct Node {
data: i32,
next: Option>,
}
fn traverse(head: &Option>) {
if head.is_none() { return; }
let mut current = head.as_ref();
loop {
println!("{}", current.unwrap().data);
current = current.unwrap().next.as_ref();
if current == head.as_ref() { break; }
}
}
This code visits each node in a circular linked list exactly once, stopping when it returns to the start.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Loop that visits each node once.
- How many times: Exactly once per node, until it loops back to the start.
As the list grows, the number of steps grows directly with the number of nodes.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | 10 visits |
| 100 | 100 visits |
| 1000 | 1000 visits |
Pattern observation: The work grows in a straight line with the number of nodes.
Time Complexity: O(n)
This means the time to traverse grows directly with the number of nodes in the list.
[X] Wrong: "Since the list is circular, traversal might never end or take infinite time."
[OK] Correct: The code stops when it returns to the start node, so it visits each node only once and ends properly.
Understanding traversal time helps you explain how to handle circular structures safely and efficiently in real code.
"What if the list was not circular but singly linked with a known end? How would the time complexity change?"
Practice
Solution
Step 1: Understand the structure of a circular linked list
A circular linked list connects the last node back to the first node, forming a circle.Step 2: Compare with a regular singly linked list
A regular singly linked list ends with a null pointer, not looping back.Final Answer:
In a circular linked list, the last node points back to the first node. -> Option BQuick Check:
Last node points to first node = A [OK]
- Thinking circular lists have two pointers per node
- Confusing circular linked list with doubly linked list
- Assuming nodes are stored in arrays
Solution
Step 1: Identify correct loop structure for circular traversal
let mut current = head; loop { println!("{}", current.data); current = current.next.unwrap(); if current == head { break; } } uses a loop that breaks when current returns to head, correctly handling circular traversal.Step 2: Check other options for errors
let mut current = head; while current != None { println!("{}", current.data); current = current.next; } uses while with None check, which is incorrect for circular lists. for node in head { println!("{}", node.data); } uses for loop on head, invalid syntax. let mut current = head; loop { println!("{}", current.data); current = current.next.unwrap(); } loops infinitely without break.Final Answer:
let mut current = head; loop { println!("{}", current.data); current = current.next.unwrap(); if current == head { break; } } -> Option AQuick Check:
Loop until current == head = A [OK]
- Using while with None check in circular list
- Forgetting to break loop on returning to head
- Using invalid for loop syntax on linked list
let mut current = head;
loop {
print!("{} ", current.data);
current = current.next.unwrap();
if current == head { break; }
}Solution
Step 1: Understand traversal logic
The loop prints current.data, moves to next, and breaks when current equals head again.Step 2: Trace the output
Starting at 10, prints 10, moves to 20, prints 20, moves to 30, prints 30, moves to 10 (head), breaks loop.Final Answer:
10 20 30 -> Option DQuick Check:
Print nodes once until back to head = D [OK]
- Printing extra head node again after loop
- Assuming infinite loop without break
- Starting traversal from wrong node
let mut current = head;
while current != head {
println!("{}", current.data);
current = current.next.unwrap();
}Solution
Step 1: Analyze loop condition
The while loop condition is current != head, but current starts as head, so condition is false immediately.Step 2: Understand effect on execution
Loop body never runs, so no traversal happens.Final Answer:
The loop never executes because current == head initially. -> Option CQuick Check:
Loop condition false at start = B [OK]
- Using while current != head instead of loop with break
- Ignoring that current starts at head
- Assuming unwrap() always safe without checking
Solution
Step 1: Understand circular list traversal for summation
We must visit each node once and stop when we return to head to avoid infinite loops.Step 2: Evaluate options
Use a loop starting at head, add current.data, move to next, break when current == head again. uses loop with break on current == head, correctly summing once. Use a while loop checking current != None, add current.data, move to next. uses None check which is invalid for circular lists. Use recursion without base case to traverse nodes and sum values. causes infinite recursion. Use a for loop over head assuming it implements Iterator. assumes Iterator trait which is not standard for linked lists.Final Answer:
Use a loop starting at head, add current.data, move to next, break when current == head again. -> Option AQuick Check:
Loop with break on head = C [OK]
- Using None checks in circular lists
- Recursing without base case causing stack overflow
- Assuming linked list implements Iterator trait
Ready to prove it?
Pass the test and this pattern moves unknown
