Reasoning Into CodeArunank Divya Sharan · Python edition← Arunank’s portfolio
Module 04 · Two Pointers and In-Place Read/Write State

031. Reverse an Array In Place

Foundation · Download this solution · All solutions and shared helpers

Problem

Reverse a mutable list in place and return the same list object. Preserve all occurrences. Empty and singleton lists are valid; no second array may be allocated.

Examples

Example 1

reverse_array([1, 2, 3, 4, 5])
=> [5, 4, 3, 2, 1]

Two swaps suffice; the middle stays in place.

Example 2

reverse_array([])
=> []

There are no unresolved pairs.

Example 3

a = [1, 2]
(reverse_array(a) is a, a)
=> (True, [2, 1])

The returned object is the supplied list.

Reveal the worked solution and reasoning

Why this mechanism works

The first and last remaining values have uniquely determined destinations in a reversal. Exchange them, then solve the smaller interior. Values outside the two frontiers are already final and never need to be visited again.

State and boundaries

left and right are inclusive indices of the unresolved region. Positions outside them are in final reversed order.

Protocol

  1. Place pointers at both ends.
  2. While left<right swap the endpoint values.
  3. Advance left and retreat right.
  4. Return the list.

Visualization

[1,2,3,4,5] -> [5,2,3,4,1]
   L   R    -> [5,4,3,2,1]
                     center stays

Python implementation

def reverse_array(nums):
    left, right = 0, len(nums) - 1
    while left < right:
        nums[left], nums[right] = nums[right], nums[left]
        left += 1
        right -= 1
    return nums

Worked execution

Recorded state changes after statements; L numbers refer to the solution file. Long traces are explicitly condensed.

reverse_array([1, 2, 3, 4, 5])

L2 reverse_array: left, right = 0, len(nums) - 1
nums=[1, 2, 3, 4, 5]; left=0; right=4

L4 reverse_array: nums[left], nums[right] = nums[right], nums[left]
nums=[5, 2, 3, 4, 1]; left=0; right=4

L5 reverse_array: left += 1
nums=[5, 2, 3, 4, 1]; left=1; right=4

L6 reverse_array: right -= 1
nums=[5, 2, 3, 4, 1]; left=1; right=3

L4 reverse_array: nums[left], nums[right] = nums[right], nums[left]
nums=[5, 4, 3, 2, 1]; left=1; right=3

L5 reverse_array: left += 1
nums=[5, 4, 3, 2, 1]; left=2; right=3

L6 reverse_array: right -= 1
nums=[5, 4, 3, 2, 1]; left=2; right=2

Result: [5, 4, 3, 2, 1]. Two swaps suffice; the middle stays in place.

reverse_array([])

L2 reverse_array: left, right = 0, len(nums) - 1
nums=[]; left=0; right=-1

Result: []. There are no unresolved pairs.

Why the solution is correct

Each exchange places two original values at their required mirrored positions. Shrinking the region protects these final values. When at most one position remains, it is either absent or already its own mirror.

Time and space

O(n) time and O(1) auxiliary space.

Common mistakes

Using nums[::-1] allocates a new list. Running the pointers through each other swaps completed pairs back.

Reasoning card

State: left and right are inclusive indices of the unresolved region. Positions outside them are in final reversed order.

Invariant: Everything outside [left,right] is already final.

Decision to rehearse: Swap first, then move both boundaries inward.

Finish: Return the list

Transfer exercise

Reverse only a specified half-open subrange [start,end), leaving everything else unchanged.