Title: Reverse an Array using Recursion
Reversing an array is one of the first problems every Java developer meets, and it is a great place to practice recursion. In this guide, you will learn how to reverse an array in place using a recursive helper method, how the call stack unwinds, how to trace the algorithm by hand, which mistakes to avoid, and how an interviewer is likely to extend the problem. By the end, you will be able to walk through the code and the recursion depth with confidence.
Understanding the Problem
You are given an array of integers and must return the same array with its elements in reverse order. For the input [10, 20, 30, 40, 50] the expected output is [50, 40, 30, 20, 10]. The reversal must happen in the array itself, so the caller does not have to copy a new array back.
Recursion fits this problem naturally. The first and last elements swap, then the problem shrinks to reversing the sub-array between them. We keep shrinking the window until the two pointers meet or cross, which is the base case that stops the recursion.
Approach
We use a helper method reverse(array, start, end) that swaps the two ends and then recurses on the inner range. The algorithm has four short steps:
- Call the helper with
start = 0andend = array.length - 1. - If
start >= end, return at once; the window is empty or has met in the middle. - Otherwise, swap
array[start]witharray[end]using a temporary variable. - Recurse with
start + 1andend - 1, shrinking the window by one on each side.
Each recursive call does exactly one swap, so the number of calls is about n / 2. Nothing new is allocated, so the mutation happens directly on the caller’s array.
Java Program
public class ReverseArrayRecursion {
public static void reverse(int[] array, int start, int end) {
if (start >= end) {
return;
}
int temp = array[start];
array[start] = array[end];
array[end] = temp;
reverse(array, start + 1, end - 1);
}
public static void main(String[] args) {
int[] numbers = {10, 20, 30, 40, 50};
reverse(numbers, 0, numbers.length - 1);
System.out.print("Reversed array: ");
for (int value : numbers) {
System.out.print(value + " ");
}
}
}Explanation of the Program
The reverse method takes the array along with two indices that mark the window still to be reversed. On every call it swaps the element at start with the element at end, then calls itself with the window shrunk by one on each side. The main method only has to pass the whole array once and print the result.
The guard if (start >= end) return; is the base case. When start == end the window has a single element and swapping it with itself is pointless. When start > end the window is empty, which happens with even-length arrays once the two pointers cross. In both situations the method returns and the previous call on the stack resumes.
The three swap lines use a local temp variable so we do not lose the original value of array[start] before writing array[end] into it. Without the temporary, both positions would end up holding the same value.
The recursive call reverse(array, start + 1, end - 1) is the shrinking step. Because the window shrinks by two indices on every call, the recursion depth is roughly n / 2, where n is the length of the array.
Step-by-Step Trace
Let us trace the algorithm on the input [7, 2, 9, 4, 1]. The expected output is [1, 4, 9, 2, 7], and the initial call is reverse(array, 0, 4).
| Call | start | end | Array before swap | Array after swap | Base case? |
|---|---|---|---|---|---|
| 1 | 0 | 4 | [7, 2, 9, 4, 1] | [1, 2, 9, 4, 7] | no |
| 2 | 1 | 3 | [1, 2, 9, 4, 7] | [1, 4, 9, 2, 7] | no |
| 3 | 2 | 2 | [1, 4, 9, 2, 7] | [1, 4, 9, 2, 7] | yes, return |
After call k, the first k and the last k positions of the array already hold their final reversed values. When the base case fires, every outer pair has been swapped and the recursion unwinds without further work.
Examples
Example 1: Odd-length array of seven elements
An odd length leaves the middle element in place because start == end when the pointers meet.
int[] input = {11, 22, 33, 44, 55, 66, 77};
reverse(input, 0, input.length - 1);
// Output: 77 66 55 44 33 22 11Example 2: Even-length array of negative numbers
An even length means the pointers cross without landing on the same index; every element is swapped exactly once.
int[] input = {-1, -2, -3, -4};
reverse(input, 0, input.length - 1);
// Output: -4 -3 -2 -1Example 3: Array containing duplicate elements
Duplicates do not break the algorithm; equal values swap into equal values and the output simply mirrors the input.
int[] input = {5, 5, 7, 7, 9};
reverse(input, 0, input.length - 1);
// Output: 9 7 7 5 5Common Mistakes to Avoid
A few recurring mistakes trip up learners when they first write this recursive reversal; watch for these in your own code.
- Swapping without a temp variable – writing
array[start] = array[end];and thenarray[end] = array[start];loses the originalarray[start], so both positions end up holding the same value. Introduce atemplocal to holdarray[start]before the first write. - Passing array.length as the initial end – the last valid index is
array.length - 1, so passing the length throwsArrayIndexOutOfBoundsExceptionon the first swap. Always callreverse(array, 0, array.length - 1). - Using start > end instead of start >= end – for odd-length arrays this adds one wasted call where
start == endand the method swaps the middle element with itself. The code still works but each wasted call uses stack space. Use>=to stop one call earlier. - Advancing only one pointer – recursing with
start + 1while keeping the sameendturns the function into infinite recursion that overflows the stack. Shrink the window from both sides on every call. - Allocating a new array inside the recursion – creating a fresh array per call wastes
O(n)memory per level, and the caller still sees the old array because the parameter is a reference copy. Mutate the passed array in place.
Edge Cases to Test
Before you call the solution done, run it against the boundary inputs that interviewers love to probe.
- Empty array
- Single-element array
- Two-element array
- Odd-length array with a middle element that stays in place
- Even-length array where every element is swapped
- Array with all duplicate elements
- Array containing
Integer.MIN_VALUEorInteger.MAX_VALUE - Null array reference
Additional Considerations
The time complexity is O(n). Each recursive call performs a constant-time swap, and there are about n / 2 calls, so the total work scales linearly with the array length.
The space complexity is O(n) for the recursion stack. Even though the algorithm does not allocate new storage, Java keeps one stack frame per active call, which can overflow for very large arrays. If you need to reverse millions of elements, prefer the iterative two-pointer loop.
The reversal happens in place, so the caller’s array is modified directly and no copy is returned. Keep that in mind if the original order is still needed elsewhere; clone the array first with array.clone() and reverse the clone.
Interview Follow-up Questions
Once the base solution is working, interviewers often extend the problem to probe depth. These are the common follow-ups.
- Can you reverse the array iteratively instead? – use a two-pointer
whileloop that swaps and advances the pointers; this drops the auxiliary space toO(1). - How would you reverse only a sub-range of the array between indices
iandj? – call the same helper withstart = iandend = j; the invariant holds on any valid sub-range. - How does your method compare with
Collections.reverse? –Collections.reverseworks onListtypes, not primitiveint[]arrays, and internally swaps iteratively; wrap the array withArrays.asListonly for object arrays. - How would you avoid stack overflow for very large arrays? – convert to the iterative two-pointer form, or split the array into chunks and reverse each chunk recursively before stitching them back.
- How would you reverse an array that does not fit in memory? – stream the file from both ends with two file pointers, swap buffered blocks, and write them back; the recursion depth stays bounded by the block count.
Conclusion
Reversing an array with recursion is a clean illustration of how a shrinking window and a well-chosen base case replace an explicit loop. Walk through the trace once by hand, write the swap carefully with a temp variable, and the rest of the program almost writes itself. Try adapting the code to reverse a char array, a String[], or only a sub-range, and compare the recursion depth with the iterative version to feel the O(n) stack cost.
You can learn more array techniques here: Arrays on Daily Java Concept.



