Traversal Forward and Backward in DSA Go - Time & Space Complexity
We want to understand how long it takes to move through a list from start to end and then back again.
How does the time needed change as the list gets bigger?
Analyze the time complexity of the following code snippet.
package main
import "fmt"
type Node struct {
value int
next *Node
prev *Node
}
func traverseForwardBackward(head *Node) {
current := head
// Traverse forward
for current != nil {
fmt.Print(current.value, " -> ")
current = current.next
}
fmt.Print("nil\n")
// Traverse backward
// Move to tail first
tail := head
for tail != nil && tail.next != nil {
tail = tail.next
}
for tail != nil {
fmt.Print(tail.value, " -> ")
tail = tail.prev
}
fmt.Print("nil\n")
}
This code moves through a doubly linked list first from the start to the end, then from the end back to the start.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Two loops that each visit every node once.
- How many times: Each loop runs once over all nodes, so together they visit nodes twice.
As the list grows, the time to go forward and backward grows roughly twice as fast.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 20 steps (10 forward + 10 backward) |
| 100 | About 200 steps |
| 1000 | About 2000 steps |
Pattern observation: The total steps grow linearly with the number of nodes, doubling because of forward and backward passes.
Time Complexity: O(n)
This means the time to traverse forward and backward grows directly in proportion to the list size.
[X] Wrong: "Because we traverse twice, the time complexity is O(n²)."
[OK] Correct: Each traversal is separate and linear, so total steps add up to 2n, which is still O(n) because constants don't change growth rate.
Understanding how traversing data structures forward and backward affects time helps you explain your code clearly and shows you know how to reason about efficiency.
"What if we only traversed forward without going backward? How would the time complexity change?"
Practice
Solution
Step 1: Understand forward traversal
Forward traversal means visiting nodes starting from the first node and moving to the last node.Step 2: Understand backward traversal
Backward traversal means visiting nodes starting from the last node and moving back to the first node.Final Answer:
Visiting nodes from the start to the end and then from the end back to the start -> Option AQuick Check:
Traversal forward and backward = visiting nodes both ways [OK]
- Confusing forward traversal with backward traversal
- Thinking traversal only goes one way
- Assuming traversal skips nodes
Solution
Step 1: Identify forward traversal start point
Forward traversal starts at the head (first node).Step 2: Identify correct pointer for forward traversal
Moving forward uses the next pointer, so node = node.next is correct.Final Answer:
for node := head; node != nil; node = node.next { fmt.Println(node.value) } -> Option BQuick Check:
Forward traversal uses head and next pointer [OK]
- Starting traversal at tail for forward direction
- Using prev pointer for forward traversal
- Confusing next and prev pointers
type Node struct {
value int
prev *Node
next *Node
}
func main() {
n1 := &Node{value: 1}
n2 := &Node{value: 2}
n3 := &Node{value: 3}
n1.next = n2
n2.prev = n1
n2.next = n3
n3.prev = n2
for node := n3; node != nil; node = node.prev {
fmt.Print(node.value, " ")
}
}Solution
Step 1: Understand backward traversal start
The loop starts at n3 (value 3) and moves backward using prev pointer.Step 2: Trace the loop values
First prints 3, then moves to n2 (2), prints 2, then moves to n1 (1), prints 1, then stops at nil.Final Answer:
3 2 1 -> Option CQuick Check:
Backward traversal prints 3 2 1 [OK]
- Confusing order of printing
- Starting traversal at head for backward
- Using next pointer instead of prev
for node := head; node != nil; node = node.prev {
fmt.Println(node.value)
}Solution
Step 1: Check traversal start and direction
The code starts at head (first node) but moves backward using prev pointer, which is incorrect because head.prev is nil.Step 2: Identify correct traversal logic
Backward traversal should start at tail, not head, when moving with prev pointer.Final Answer:
Starting traversal at head but moving backward with prev pointer -> Option AQuick Check:
Backward traversal must start at tail [OK]
- Starting backward traversal at head
- Confusing loop condition
- Ignoring pointer directions
Solution
Step 1: Traverse forward and print all nodes
Start from head and print each node until tail inclusive.Step 2: Traverse backward starting from tail.prev to avoid duplicate tail
Start backward traversal from tail.prev to head to avoid printing tail twice.Final Answer:
Traverse forward printing all nodes, then traverse backward starting from tail.prev to head -> Option DQuick Check:
Skip last node in backward traversal to avoid duplicate print [OK]
- Printing tail twice by starting backward at tail
- Starting backward traversal incorrectly
- Confusing traversal directions
Ready to prove it?
Pass the test and this pattern moves unknown
