Traversal Forward and Backward in DSA C++ - Time & Space Complexity
We want to understand how long it takes to move through a list from start to end and then back from end to start.
How does the time needed change as the list gets bigger?
Analyze the time complexity of the following code snippet.
void traverseForwardBackward(int arr[], int n) {
// Traverse forward
for (int i = 0; i < n; i++) {
// process arr[i]
}
// Traverse backward
for (int i = n - 1; i >= 0; i--) {
// process arr[i]
}
}
This code goes through the array from the first element to the last, then goes back from the last element to the first.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Two separate loops each visiting every element once.
- How many times: Each loop runs n times, where n is the size of the array.
As the array grows, the total steps grow roughly twice as fast because we go forward and backward.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | 20 (10 forward + 10 backward) |
| 100 | 200 (100 forward + 100 backward) |
| 1000 | 2000 (1000 forward + 1000 backward) |
Pattern observation: The total operations grow linearly with input size, doubling because of two passes.
Time Complexity: O(n)
This means the time to complete grows directly in proportion to the number of elements.
[X] Wrong: "Because there are two loops, the time complexity is O(n²)."
[OK] Correct: The loops run one after another, not nested, so their times add up, not multiply.
Understanding how multiple passes over data add up helps you explain and optimize code clearly in interviews.
"What if we combined the forward and backward traversal into a single loop that processes two elements per iteration? How would the time complexity change?"
Practice
Solution
Step 1: Understand singly linked list structure
A singly linked list has nodes connected only forward, from head to tail.Step 2: Define forward traversal
Forward traversal means visiting nodes starting at the head and moving to the tail in order.Final Answer:
Visiting nodes from the head to the tail in order -> Option AQuick Check:
Forward traversal = head to tail [OK]
- Confusing forward with backward traversal
- Thinking traversal can skip nodes
- Assuming random order traversal
Solution
Step 1: Understand vector indexing in C++
Vectors are zero-indexed, so valid indices are 0 to size()-1.Step 2: Check loop boundaries
for (int i = 0; i < vec.size(); i++) { cout << vec[i] << ' '; } loops from 0 to size()-1, correctly accessing all elements forward.Final Answer:
for (int i = 0; i < vec.size(); i++) { cout << vec[i] << ' '; } -> Option AQuick Check:
Forward vector traversal uses i from 0 to size()-1 [OK]
- Using i <= vec.size() causing out-of-range error
- Starting loop from 1 instead of 0
- Looping backwards for forward traversal
std::vector<int> v = {10, 20, 30};
for (int i = v.size() - 1; i >= 0; i--) {
std::cout << v[i] << ' ';
}Solution
Step 1: Analyze loop start and end
Loop starts at v.size()-1 = 2 and decrements to 0 inclusive.Step 2: Trace output values
v[2] = 30, v[1] = 20, v[0] = 10 printed in that order with spaces.Final Answer:
30 20 10 -> Option BQuick Check:
Backward traversal prints 30 20 10 [OK]
- Confusing forward and backward order
- Off-by-one errors in loop condition
- Expecting runtime error due to unsigned index
std::vector<int> v = {1, 2, 3};
for (int i = v.size(); i >= 0; i--) {
std::cout << v[i] << ' ';
}Solution
Step 1: Check loop start index
v.size() is 3, but valid indices are 0 to 2, so v[3] is invalid.Step 2: Understand consequences
Accessing v[3] causes out-of-range error or undefined behavior.Final Answer:
Loop starts at v.size(), which is out of range -> Option CQuick Check:
Index must be less than size() [OK]
- Starting loop at size() instead of size()-1
- Ignoring vector index bounds
- Assuming no error on out-of-range access
struct Node {
int data;
Node* prev;
Node* next;
};
Node* tail = /* points to node with data 3 */;
// Which loop prints backward traversal?
Solution
Step 1: Understand doubly linked list backward traversal
Backward traversal moves from tail to head using prev pointers.Step 2: Check loop correctness
for (Node* cur = tail; cur != nullptr; cur = cur->prev) { std::cout << cur->data << ' '; } starts at tail and moves using cur = cur->prev until nullptr, printing all nodes backward.Final Answer:
for (Node* cur = tail; cur != nullptr; cur = cur->prev) { std::cout << cur->data << ' '; } -> Option DQuick Check:
Backward traversal uses prev pointer from tail [OK]
- Using next pointer for backward traversal
- Stopping loop before head (checking cur->prev != nullptr)
- Starting from head instead of tail
Ready to prove it?
Pass the test and this pattern moves unknown
