DSA Tutorial
🔍

Array Traversal

What Is Array Traversal?

Traversal means visiting every element in an array — or a defined subset of elements — in a controlled order. It is the most fundamental operation you perform on an array, and nearly every other array algorithm is built on top of it.

The word "visiting" is intentional. Traversal is not just printing. Visiting an element might mean:

  • Checking if it satisfies a condition
  • Accumulating it into a sum or product
  • Comparing it against a running value
  • Deciding whether to skip, swap, or transform it

The traversal pattern you choose determines what information is available at each step. Choosing the right pattern for the problem is as important as choosing the right algorithm.

Traversal 1: Forward Traversal (Index-Based)

The most common pattern. Visit every element from index 0 to index length - 1 in order.

Use this when you need both the element's value and its position (index) at the same time. The index lets you look ahead (arr[i+1]), look behind (arr[i-1]), or write to the same position (arr[i] = newValue).

Java
1public class ForwardTraversal { 2 3 public static void main(String[] args) { 4 int[] prices = {120, 85, 200, 95, 150, 60}; 5 6 // Index-based forward traversal 7 // Use when you need both value and position 8 System.out.println("All prices:"); 9 for (int i = 0; i < prices.length; i++) { 10 System.out.println(" Index " + i + ": " + prices[i]); 11 } 12 13 // Count prices above 100 14 int count = 0; 15 for (int i = 0; i < prices.length; i++) { 16 if (prices[i] > 100) { 17 count++; 18 } 19 } 20 System.out.println("Prices above 100: " + count); 21 } 22}
Output:
All prices:
  Index 0: 120
  Index 1: 85
  Index 2: 200
  Index 3: 95
  Index 4: 150
  Index 5: 60
Prices above 100: 3

Traversal 2: For-Each (Enhanced For Loop)

When you only need the element's value and do not need to write back to the array or access neighboring elements, a for-each loop is cleaner and less error-prone.

For-each eliminates the index entirely — no off-by-one risk, no boundary to manage.

Java
1public class ForEachTraversal { 2 3 public static void main(String[] args) { 4 int[] temperatures = {22, 19, 25, 17, 28, 21}; 5 6 // For-each — use when you only need values, not positions 7 int sum = 0; 8 for (int temp : temperatures) { 9 sum += temp; 10 } 11 12 double average = (double) sum / temperatures.length; 13 System.out.println("Sum: " + sum); 14 System.out.printf("Average: %.2f%n", average); 15 16 // Check if any temperature is dangerously high 17 boolean dangerousHeat = false; 18 for (int temp : temperatures) { 19 if (temp > 26) { 20 dangerousHeat = true; 21 break; // Stop as soon as we find one 22 } 23 } 24 System.out.println("Dangerous heat: " + dangerousHeat); 25 } 26}
Output:
Sum:     132
Average: 22.00
Dangerous heat: true

Index-Based vs For-Each: When to Use Which

Use index-based (for i = 0 to n-1) when:
  - You need to write back to the array:    arr[i] = newValue
  - You need to look ahead:                 arr[i+1]
  - You need to look behind:                arr[i-1]
  - You need to compare two positions:      arr[i] vs arr[j]
  - You need to traverse two arrays at once

Use for-each when:
  - You only need to read element values
  - No index arithmetic is needed
  - Cleaner, less error-prone code is preferred

Traversal 3: Backward Traversal

Traverse from the last element to the first. Use this when processing order matters and the problem naturally works from right to left — reversing a result, undoing operations, or comparing symmetric positions.

Java
1public class BackwardTraversal { 2 3 public static void main(String[] args) { 4 int[] numbers = {1, 2, 3, 4, 5}; 5 6 // Backward traversal — start at length-1, stop at 0 (inclusive) 7 System.out.print("Reversed: "); 8 for (int i = numbers.length - 1; i >= 0; i--) { 9 System.out.print(numbers[i] + " "); 10 } 11 System.out.println(); 12 13 // Practical use: find the last even number 14 int lastEven = -1; 15 for (int i = numbers.length - 1; i >= 0; i--) { 16 if (numbers[i] % 2 == 0) { 17 lastEven = numbers[i]; 18 break; // Stop at the first even from the right 19 } 20 } 21 System.out.println("Last even number: " + lastEven); 22 } 23}
Output:
Reversed: 5 4 3 2 1
Last even number: 4

Dry Run: Backward Traversal on [1, 2, 3, 4, 5]

Array:  [1, 2, 3, 4, 5]
Index:   0  1  2  3  4

i = 4 → arr[4] = 5  → print 5
i = 3 → arr[3] = 4  → print 4
i = 2 → arr[2] = 3  → print 3
i = 1 → arr[1] = 2  → print 2
i = 0 → arr[0] = 1  → print 1

i = -1 → condition i >= 0 is false → loop ends

Output: 5 4 3 2 1

Common mistake: using i > 0 instead of i >= 0
  → skips index 0 → misses the first element

Traversal 4: Partial Traversal (Subarray)

Sometimes you do not need the entire array — only a specific range from index left to index right. This is partial traversal, and it is the foundation of sliding window, divide and conquer, and binary search.

Java
1public class PartialTraversal { 2 3 // Traverse a subarray from index left to right (inclusive) 4 public static int subarraySum(int[] arr, int left, int right) { 5 int sum = 0; 6 7 // Only visit elements within the specified range 8 for (int i = left; i <= right; i++) { 9 sum += arr[i]; 10 } 11 12 return sum; 13 } 14 15 public static void main(String[] args) { 16 int[] arr = {3, 7, 1, 8, 4, 5, 2, 9}; 17 18 System.out.println("Full array sum: " + subarraySum(arr, 0, arr.length - 1)); 19 System.out.println("Sum from index 2 to 5: " + subarraySum(arr, 2, 5)); 20 System.out.println("Sum from index 4 to 7: " + subarraySum(arr, 4, 7)); 21 } 22}
Output:
Full array sum:        39
Sum from index 2 to 5: 18
Sum from index 4 to 7: 20

Traversal 5: Skipping Elements

Visit every kth element, every even index, every odd index, or any other regular pattern. This appears in problems involving alternating positions, stride-based processing, or specific offsets.

Java
1public class SkipTraversal { 2 3 public static void main(String[] args) { 4 int[] arr = {10, 20, 30, 40, 50, 60, 70, 80}; 5 6 // Even indices only (0, 2, 4, 6) 7 System.out.print("Even indices: "); 8 for (int i = 0; i < arr.length; i += 2) { 9 System.out.print(arr[i] + " "); 10 } 11 System.out.println(); 12 13 // Odd indices only (1, 3, 5, 7) 14 System.out.print("Odd indices: "); 15 for (int i = 1; i < arr.length; i += 2) { 16 System.out.print(arr[i] + " "); 17 } 18 System.out.println(); 19 20 // Every third element (0, 3, 6) 21 System.out.print("Every 3rd: "); 22 for (int i = 0; i < arr.length; i += 3) { 23 System.out.print(arr[i] + " "); 24 } 25 System.out.println(); 26 } 27}
Output:
Even indices:  10 30 50 70
Odd indices:   20 40 60 80
Every 3rd:     10 40 70

Traversal 6: Traversal with enumerate / Index-Value Pairs

When you need both the index and the value simultaneously — especially for tracking positions of elements that satisfy a condition — use index-value traversal. In Python this is enumerate, in Java and C++ it is a standard indexed loop, in JavaScript it is entries().

Java
1public class IndexValueTraversal { 2 3 public static void main(String[] args) { 4 int[] scores = {72, 88, 55, 91, 63, 77, 48, 95}; 5 int threshold = 80; 6 7 // Find all indices where score exceeds threshold 8 System.out.println("High scorers (score > " + threshold + "):"); 9 for (int i = 0; i < scores.length; i++) { 10 if (scores[i] > threshold) { 11 System.out.println(" Student " + i + ": score = " + scores[i]); 12 } 13 } 14 15 // Find the index of the maximum element 16 int maxIndex = 0; 17 for (int i = 1; i < scores.length; i++) { 18 if (scores[i] > scores[maxIndex]) { 19 maxIndex = i; // Track position, not just value 20 } 21 } 22 System.out.println("Highest scorer: Student " + maxIndex 23 + " with score " + scores[maxIndex]); 24 } 25}
Output:
High scorers (score > 80):
  Student 1: score = 88
  Student 3: score = 91
  Student 7: score = 95
Highest scorer: Student 7 with score 95

Traversal 7: Two-Pointer Traversal

Use one pointer at each end of the array, moving them toward each other. This pattern appears when a problem involves comparing or combining elements from opposite ends — checking palindromes, moving zeros to one end, partitioning around a pivot.

This is not the full two-pointer technique for pair-sum problems (which involves sorted arrays). This is the structural pattern of having two indices converging inward.

Java
1public class TwoPointerTraversal { 2 3 // Check if array is a palindrome using two-pointer traversal 4 public static boolean isPalindrome(int[] arr) { 5 int left = 0; 6 int right = arr.length - 1; 7 8 // Move both pointers inward, comparing at each step 9 while (left < right) { 10 if (arr[left] != arr[right]) { 11 return false; // Mismatch — not a palindrome 12 } 13 left++; // Move left pointer right 14 right--; // Move right pointer left 15 } 16 17 return true; // All pairs matched 18 } 19 20 public static void main(String[] args) { 21 int[] a = {1, 2, 3, 2, 1}; 22 int[] b = {1, 2, 3, 4, 5}; 23 int[] c = {5, 5, 5}; 24 int[] d = {1}; 25 26 System.out.println("[1,2,3,2,1] palindrome: " + isPalindrome(a)); 27 System.out.println("[1,2,3,4,5] palindrome: " + isPalindrome(b)); 28 System.out.println("[5,5,5] palindrome: " + isPalindrome(c)); 29 System.out.println("[1] palindrome: " + isPalindrome(d)); 30 } 31}
Output:
[1,2,3,2,1] palindrome: true
[1,2,3,4,5] palindrome: false
[5,5,5]     palindrome: true
[1]         palindrome: true

Dry Run: Palindrome Check on [1, 2, 3, 2, 1]

Array:  [1, 2, 3, 2, 1]
         L           R

Step 1: left=0, right=4 → arr[0]=1, arr[4]=1 → match → left=1, right=3
Step 2: left=1, right=3 → arr[1]=2, arr[3]=2 → match → left=2, right=2
Step 3: left=2 >= right=2 → condition false → exit loop

Return true — all symmetric pairs matched

Why left < right (not <=)?
  When left == right, we are at the middle element of an odd-length array.
  A single element always matches itself — no comparison needed.
  Checking it would be wasted work with no correctness benefit.

Handling Edge Cases in Traversal

Every traversal must handle these cases correctly. Forgetting them is the most common source of bugs in array problems.

Empty Array

Before any traversal that makes assumptions about array content, check for empty input:

Java
1public class EdgeCases { 2 3 public static int findMax(int[] arr) { 4 // Guard: empty array has no maximum 5 if (arr.length == 0) { 6 throw new IllegalArgumentException("Array is empty"); 7 } 8 9 int max = arr[0]; // Safe — we know arr has at least one element 10 for (int i = 1; i < arr.length; i++) { 11 if (arr[i] > max) max = arr[i]; 12 } 13 return max; 14 } 15 16 public static void main(String[] args) { 17 int[] normal = {3, 1, 7, 2}; 18 System.out.println("Max of [3,1,7,2]: " + findMax(normal)); 19 20 int[] single = {42}; 21 System.out.println("Max of [42]: " + findMax(single)); 22 23 // Empty array would throw — handle before calling 24 int[] empty = {}; 25 System.out.println("Empty? " + (empty.length == 0 ? "yes, skip" : findMax(empty))); 26 } 27}
Output:
Max of [3,1,7,2]: 7
Max of [42]:      42
Empty? yes, skip

The Critical Off-By-One Boundaries

FORWARD traversal:
  Correct:   i = 0; i < arr.length      → visits 0, 1, ..., n-1
  Wrong:     i = 0; i <= arr.length     → visits 0, 1, ..., n → CRASH at n
  Wrong:     i = 1; i < arr.length      → skips index 0 (first element)

BACKWARD traversal:
  Correct:   i = arr.length - 1; i >= 0 → visits n-1, n-2, ..., 0
  Wrong:     i = arr.length;     i >= 0 → starts at arr[n] → OUT OF BOUNDS
  Wrong:     i = arr.length - 1; i > 0  → skips index 0 (first element)

PARTIAL traversal (left to right inclusive):
  Correct:   i = left; i <= right        → visits left, left+1, ..., right
  Wrong:     i = left; i < right         → misses arr[right] (off by one)

TWO-POINTER converging:
  Correct:   while (left < right)        → stops when pointers meet or cross
  Wrong:     while (left <= right)       → compares middle element to itself (harmless
                                           but unnecessary; logic depends on problem)

Traversal Pattern Summary

PatternLoop StyleWhen to Use
Forward index-basedfor i = 0 to n-1Need index, write-back, or look-ahead
Forward for-eachfor each x in arrOnly need values, no index needed
Backwardfor i = n-1 to 0Right-to-left processing, finding last match
Partialfor i = left to rightSubarrays, divide and conquer, binary search
Skippingi += k in loopEvery kth element, alternating positions
Index-value pairsenumerate / entries()Need both index and value cleanly
Two-pointer convergingleft++, right--Palindrome, symmetric comparison, partitioning

Interview Questions

Q: When should you use a for-each loop versus an index-based for loop?

Use for-each when you only need to read element values and the index is irrelevant. It is cleaner and eliminates the risk of off-by-one errors. Use an index-based for loop when you need to write back to the array (arr[i] = value), access neighboring elements (arr[i+1]), traverse two arrays simultaneously using the same index, or use the index as part of the computation.

Q: How do you find the index of the maximum element, not just the maximum value?

Track maxIndex initialized to 0, and update it whenever you find a larger value. After traversal, arr[maxIndex] is the maximum value and maxIndex is its position. Never use a for-each loop for this — you need the index, which for-each does not expose.

Q: What is the correct loop boundary for backward traversal?

Start at arr.length - 1 (last valid index) and use i >= 0 as the stopping condition (inclusive of index 0). A common mistake is using i > 0 which misses the element at index 0, or starting at arr.length which accesses one past the end.

Q: How does two-pointer traversal reduce work compared to nested loops?

Nested loops check every combination — O(n²) comparisons. Two-pointer traversal uses one pointer from each end and moves them inward based on a comparison — O(n) comparisons total. Each pointer moves at most n times, and together they cover all necessary comparisons without redundancy. This works because the structure of the problem (symmetric comparison, sorted order) means you can eliminate large sections of the search space with each step.

FAQs

What is the difference between range(n) and range(len(arr)) in Python?

range(n) generates indices 0 through n-1 when n is a known constant. range(len(arr)) generates the same indices dynamically based on the array's actual length. Always use range(len(arr)) when traversing an array — it is correct regardless of array size. Using range(n) with a hardcoded n is fragile and breaks if the array changes size.

Why does Python's enumerate start at 0 by default, and can you change it?

enumerate(arr) produces (0, arr[0]), (1, arr[1]), .... You can change the starting index with enumerate(arr, start=1) to get (1, arr[0]), (2, arr[1]), .... This is useful when displaying "Student 1" through "Student n" to users, but for algorithmic purposes always use 0-based indexing.

Is it safe to modify an array while traversing it?

Modifying elements at the current index or positions you have already passed is safe. Modifying the length of the array during traversal (inserting or removing elements) is dangerous — it shifts elements and invalidates your index. In Python, never use list.remove() or list.insert() inside a for i in range(len(arr)) loop. In Java, never modify an ArrayList's size inside a for-each loop — use an index-based loop instead or collect changes and apply them after traversal.

When should you break out of a traversal early?

When the problem asks for the first occurrence of something (first element matching a condition, first duplicate, first index where a value appears). Once found, further traversal is wasted work. Always break or return immediately upon finding the answer. Continuing to traverse wastes O(n) time that could be O(1) in the best case.

Quick Quiz

Question 1: You need to find the index of the last element greater than 50 in an array. Which traversal is most efficient?

  • A) Forward traversal, record every matching index, return the last one
  • B) Backward traversal, return the first matching index found
  • C) For-each loop, track the matching value
  • D) Two-pointer traversal from both ends

Answer: B) Backward traversal, return the first match found. Traversing from right to left, the first element you find that is greater than 50 is the last such element in forward order. Break immediately — O(1) best case. Forward traversal with tracking finds the correct answer but cannot break early, costing O(n) in all cases.

Question 2: What is wrong with this loop: for (int i = 0; i <= arr.length; i++)?

  • A) It starts at the wrong index
  • B) It accesses arr[arr.length] which is out of bounds
  • C) It skips the last element
  • D) Nothing — it is correct

Answer: B) It accesses arr[arr.length] which is out of bounds. Valid indices run from 0 to arr.length - 1. When i == arr.length, accessing arr[i] reaches one past the end of the array. The correct condition is i < arr.length.

Question 3: You want to visit elements at indices 2, 4, 6, 8 in an array of length 10. What is the correct loop?

  • A) for i = 0 to 9, if i % 2 == 0
  • B) for i = 2; i < 10; i += 2
  • C) for i = 1; i < 10; i += 2
  • D) for i = 0; i < 10; i++ and check i > 1

Answer: B) for i = 2; i < 10; i += 2. Start at index 2, stop before index 10, increment by 2. This visits exactly indices 2, 4, 6, 8. Option A also works but wastes half the iterations checking the condition.

Question 4: In the two-pointer palindrome check, why is the stopping condition left < right rather than left <= right?

  • A) To avoid an infinite loop
  • B) When left == right, both pointers are at the middle element — comparing it to itself is unnecessary
  • C) To prevent out-of-bounds access
  • D) left <= right would give wrong results

Answer: B) When left == right, both pointers are at the middle element — comparing it to itself is unnecessary. The middle element of an odd-length array always matches itself. Stopping at left < right correctly handles both odd-length arrays (stops at the middle) and even-length arrays (stops when pointers cross). The result is correct either way, but left < right avoids one unnecessary comparison.

Summary

Array traversal is the foundation of every array algorithm. The pattern you choose controls what information is available at each step and how efficiently the algorithm runs.

The key traversal patterns to carry forward:

  • Forward index-based (for i = 0; i < n; i++) — when you need index, write-back, or look-ahead
  • Forward for-each (for each x in arr) — when only values are needed, cleaner and safer
  • Backward (for i = n-1; i >= 0; i--) — right-to-left, finding last occurrence, reverse processing
  • Partial (for i = left; i <= right; i++) — subarrays, divide and conquer, range operations
  • Skipping (i += k) — every kth element, alternating positions
  • Index-value pairs (enumerate, entries()) — clean access to both index and value
  • Two-pointer converging (left++, right--) — symmetric comparison, partitioning

Always verify two boundaries before traversal: is the array empty, and are the loop bounds correct? Off-by-one errors and empty-array crashes are the two most common traversal bugs in every interview and every codebase.

In the next topic, you will explore Array Operations — insert, delete, search, and update with their true time complexities and the implementation details that matter in interviews.

Array Traversal