Language Selection
Choose your preferred programming language
Reverse an Array
Problem Statement
Given an array of integers, reverse the order of elements in the array. You can modify the array in-place or create a new array.
Input/Output Specifications
- Input: An array of integers
numswhere0 <= nums.length <= 10^5and-10^9 <= nums[i] <= 10^9 - Output: The same array with elements in reverse order
Constraints
- The array can be empty
- Array elements can be negative, positive, or zero
- You should aim for an in-place solution for optimal space complexity
Examples
Example 1:
Input: nums = [1, 2, 3, 4, 5]
Output: [5, 4, 3, 2, 1]
Explanation: Elements are reversed in place.
Example 2:
Input: nums = [7, 9]
Output: [9, 7]
Explanation: Two elements are swapped.
Example 3:
Input: nums = []
Output: []
Explanation: Empty array remains empty.
Example 4:
Input: nums = [42]
Output: [42]
Explanation: Single element array remains unchanged.
Solution Approaches
Approach 1: Two Pointers (In-Place) - Optimal
Algorithm Explanation:
- Use two pointers: one at the start (left) and one at the end (right) of the array
- Swap the elements at these positions
- Move the left pointer forward and right pointer backward
- Continue until the pointers meet or cross each other
- Return the modified array
Implementation:
Python:
def reverse_array(nums):
"""
Reverse array using two pointers approach
Time: O(n)
Space: O(1)
"""
if not nums:
return nums
left = 0
right = len(nums) - 1
while left < right:
# Swap elements at left and right positions
nums[left], nums[right] = nums[right], nums[left]
left += 1
right -= 1
return nums
# Alternative using built-in reverse
def reverse_array_builtin(nums):
"""
Reverse array using built-in reverse method
Time: O(n)
Space: O(1)
"""
nums.reverse()
return nums
# Alternative using slicing (creates new array)
def reverse_array_slicing(nums):
"""
Reverse array using slicing
Time: O(n)
Space: O(n)
"""
return nums[::-1]
Java:
class Solution {
/**
* Reverse array using two pointers approach
* Time: O(n)
* Space: O(1)
*/
public int[] reverseArray(int[] nums) {
if (nums == null || nums.length <= 1) {
return nums;
}
int left = 0;
int right = nums.length - 1;
while (left < right) {
// Swap elements at left and right positions
int temp = nums[left];
nums[left] = nums[right];
nums[right] = temp;
left++;
right--;
}
return nums;
}
// Alternative using Collections.reverse
public Integer[] reverseArrayList(Integer[] nums) {
List<Integer> list = Arrays.asList(nums);
Collections.reverse(list);
return list.toArray(new Integer[0]);
}
}
Go:
// reverseArray - Reverse array using two pointers approach
// Time: O(n)
// Space: O(1)
func reverseArray(nums []int) []int {
if len(nums) <= 1 {
return nums
}
left := 0
right := len(nums) - 1
for left < right {
// Swap elements at left and right positions
nums[left], nums[right] = nums[right], nums[left]
left++
right--
}
return nums
}
// Alternative creating new slice
func reverseArrayNew(nums []int) []int {
if len(nums) <= 1 {
return nums
}
result := make([]int, len(nums))
for i := 0; i < len(nums); i++ {
result[i] = nums[len(nums)-1-i]
}
return result
}
JavaScript:
/**
* Reverse array using two pointers approach
* Time: O(n)
* Space: O(1)
*/
function reverseArray(nums) {
if (!nums || nums.length <= 1) {
return nums;
}
let left = 0;
let right = nums.length - 1;
while (left < right) {
// Swap elements at left and right positions
[nums[left], nums[right]] = [nums[right], nums[left]];
left++;
right--;
}
return nums;
}
// Alternative using built-in reverse
function reverseArrayBuiltin(nums) {
return nums.reverse();
}
// Alternative using reduce
function reverseArrayReduce(nums) {
return nums.reduce((acc, curr, i) => {
acc[nums.length - 1 - i] = curr;
return acc;
}, new Array(nums.length));
}
C#:
public class Solution {
/// <summary>
/// Reverse array using two pointers approach
/// Time: O(n)
/// Space: O(1)
/// </summary>
public int[] ReverseArray(int[] nums) {
if (nums == null || nums.Length <= 1) {
return nums;
}
int left = 0;
int right = nums.Length - 1;
while (left < right) {
// Swap elements at left and right positions
int temp = nums[left];
nums[left] = nums[right];
nums[right] = temp;
left++;
right--;
}
return nums;
}
// Alternative using Array.Reverse
public int[] ReverseArrayBuiltin(int[] nums) {
if (nums == null) return nums;
Array.Reverse(nums);
return nums;
}
// Alternative using LINQ
public int[] ReverseArrayLinq(int[] nums) {
if (nums == null) return nums;
return nums.Reverse().ToArray();
}
}
Complexity Analysis:
- Time Complexity: O(n) - We visit each element at most once
- Space Complexity: O(1) - Only using a constant amount of extra space for variables
Trade-offs:
- In-place modification is memory efficient
- Simple and intuitive algorithm
- No additional data structures needed
- Modifies the original array (consider if this is desired behavior)
Approach 2: Iterative with New Array
Algorithm Explanation:
- Create a new array of the same size
- Iterate through the original array from the end to the beginning
- Place each element in the new array from the start
- Return the new array
Implementation:
Python:
def reverse_array_new(nums):
"""
Reverse array by creating new array
Time: O(n)
Space: O(n)
"""
if not nums:
return nums
result = [0] * len(nums)
for i in range(len(nums)):
result[i] = nums[len(nums) - 1 - i]
return result
Java:
class Solution {
/**
* Reverse array by creating new array
* Time: O(n)
* Space: O(n)
*/
public int[] reverseArrayNew(int[] nums) {
if (nums == null || nums.length == 0) {
return nums;
}
int[] result = new int[nums.length];
for (int i = 0; i < nums.length; i++) {
result[i] = nums[nums.length - 1 - i];
}
return result;
}
}
Go:
// reverseArrayNew - Reverse array by creating new array
// Time: O(n)
// Space: O(n)
func reverseArrayNew(nums []int) []int {
if len(nums) == 0 {
return nums
}
result := make([]int, len(nums))
for i := 0; i < len(nums); i++ {
result[i] = nums[len(nums)-1-i]
}
return result
}
JavaScript:
/**
* Reverse array by creating new array
* Time: O(n)
* Space: O(n)
*/
function reverseArrayNew(nums) {
if (!nums || nums.length === 0) {
return nums;
}
const result = new Array(nums.length);
for (let i = 0; i < nums.length; i++) {
result[i] = nums[nums.length - 1 - i];
}
return result;
}
C#:
public class Solution {
/// <summary>
/// Reverse array by creating new array
/// Time: O(n)
/// Space: O(n)
/// </summary>
public int[] ReverseArrayNew(int[] nums) {
if (nums == null || nums.Length == 0) {
return nums;
}
int[] result = new int[nums.Length];
for (int i = 0; i < nums.Length; i++) {
result[i] = nums[nums.Length - 1 - i];
}
return result;
}
}
Complexity Analysis:
- Time Complexity: O(n) - We visit each element once
- Space Complexity: O(n) - We create a new array of the same size
Trade-offs:
- Preserves the original array
- Requires additional memory
- Good when you need to keep the original array unchanged
- Slightly more cache-friendly for very large arrays
Key Insights
- Two Pointers Pattern: This is a fundamental pattern for array problems that need to process elements from both ends
- In-place vs New Array: Choose based on whether you need to preserve the original array
- Swap Technique: The simultaneous swap is a common idiom in many languages
- Edge Cases: Empty arrays and single-element arrays require special handling
Edge Cases
- Empty Array:
[]→ Returns[] - Single Element:
[5]→ Returns[5] - Two Elements:
[1, 2]→ Returns[2, 1] - All Same Elements:
[3, 3, 3]→ Returns[3, 3, 3] - Large Array: Performance should remain consistent
How Solutions Handle Edge Cases:
- Empty array: Check length before processing
- Single element: Left and right pointers never enter the while loop
- Two elements: One swap occurs, then pointers meet
- All same: Algorithm works correctly, swapping identical values
Test Cases
def test_reverse_array():
# Basic case
assert reverse_array([1, 2, 3, 4, 5]) == [5, 4, 3, 2, 1]
# Two elements
assert reverse_array([7, 9]) == [9, 7]
# Empty array
assert reverse_array([]) == []
# Single element
assert reverse_array([42]) == [42]
# All same elements
assert reverse_array([5, 5, 5]) == [5, 5, 5]
# Negative numbers
assert reverse_array([-1, -2, -3]) == [-3, -2, -1]
# Mixed positive and negative
assert reverse_array([-1, 0, 1]) == [1, 0, -1]
# Large array
large_array = list(range(1000))
expected = list(range(999, -1, -1))
assert reverse_array(large_array) == expected
print("All tests passed!")
test_reverse_array()
Follow-up Questions
- Reverse Subarray: How would you reverse only a portion of the array?
- Reverse in Groups: How would you reverse every k elements?
- Rotate vs Reverse: What’s the difference between rotation and reversal?
- Linked List: How would you adapt this for a linked list?
- String Reversal: How does string reversal differ from array reversal?
Common Mistakes
Index Out of Bounds: Not handling empty arrays properly
- Problem: Accessing
nums[0]when array is empty - Solution: Check array length before processing
- Problem: Accessing
Infinite Loop: Wrong loop condition
- Problem: Using
while left <= rightinstead ofwhile left < right - Solution: Use strict inequality to prevent swapping middle element with itself
- Problem: Using
Not Handling Edge Cases: Forgetting single element arrays
- Problem: Unnecessary processing for arrays of length 0 or 1
- Solution: Early return for these cases
Modifying vs Creating: Confusion about in-place vs new array
- Problem: Expecting original array to be unchanged when using in-place method
- Solution: Clearly document behavior and choose appropriate method
Interview Tips
- Ask Clarifying Questions: Should the reversal be in-place or create a new array?
- Start Simple: Begin with the two-pointer approach - it’s optimal and intuitive
- Discuss Alternatives: Mention built-in methods but implement the manual approach
- Edge Cases First: Handle empty and single-element arrays early
- Space-Time Trade-offs: Discuss when in-place is better vs when preserving original is needed
Concept Explanations
Two Pointers Technique: This problem demonstrates the fundamental two-pointers pattern where pointers move toward each other from opposite ends. This pattern is essential for many array and string problems.
In-Place Operations: Reversing an array in-place showcases how to modify data structures without using additional memory, which is crucial for memory-constrained environments.
When to Apply: Use this pattern when you need to process elements from both ends of a sequence, such as palindrome checking, finding pairs, or any symmetric operations.