๐ŸŽ“ A1Learner
๐Ÿ”

DSA Reversing an Array in Place

Reversing a list in place flips its order inside the same list. Two indices start at the ends and swap pairs as they walk toward each other.

The problem

Reversing a list in place flips the order of its values. The same list holds the result. No second list is built.

The first value trades places with the last value. The second value trades with the second last value. The pattern continues inward.

The cases used in this article

cases = [
    [1, 2, 3, 4, 5],
    ['Ana', 'Bo', 'Cy', 'Dee'],
    [1, 2, 3],
    [7],
]
for values in cases:
    print(values, '->', values[::-1])

Intuition

The first idea is often to build a new list. Read the old list from the back. Append each value to the new list.

That idea gives the right order. It also spends a second list of the same size. The problem asks for the flip inside the same list, so the extra list is the cost to remove.

Building a second list

values = [1, 2, 3, 4, 5]
flipped = []
for index in range(len(values) - 1, -1, -1):
    flipped.append(values[index])
print('new list:', flipped)
print('original:', values)
print('extra cells used:', len(flipped))

Brute force

A slow in-place method uses pop and insert. The last value belongs at the front after a reversal. The next last value belongs in the second cell, and so on.

Each pop and insert shifts the values between the two ends. The shifts repeat work that a single swap would finish.

Shifting values into place

values = [1, 2, 3, 4, 5]
moves = 0
for front in range(len(values) - 1):
    value = values.pop()
    moves += 1
    for index in range(front, len(values)):
        moves += 1
    values.insert(front, value)
print('result:', values)
print('pops, inserts and shifted cells counted as moves:', moves)

The method works. Its cost grows fast, because later shifts move over ground that earlier shifts already crossed. One swap per pair avoids the shifting entirely.

The optimal solution: swap pairs from the ends

The key idea is one swap per pair. Two indices start at the ends and walk toward each other, swapping the values they point at.

The in-place reversal solution

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

cases = [
    [1, 2, 3, 4, 5],
    ['Ana', 'Bo', 'Cy', 'Dee'],
    [1, 2, 3],
    [7],
]
for values in cases:
    print(values, '->', reverse_in_place(list(values)))

Walkthrough

Take the list [1, 2, 3, 4, 5]. The left index starts at 0. The right index starts at 4.

The list after each swap

values = [1, 2, 3, 4, 5]
left = 0
right = len(values) - 1
while left < right:
    values[left], values[right] = values[right], values[left]
    print('swapped positions', left, 'and', right, ':', values)
    left += 1
    right -= 1
print('indices meet at value:', values[left])

The first swap settles 5 and 1. The second swap settles 4 and 2. The indices then meet at 3, and the middle value stays put.

Complexity

Time is O(n). Each swap settles two values, and a list of n values needs n // 2 swaps.

Space is O(1). Two indices and one swap are the only extra storage.

Counting swaps as the list grows

def swaps_needed(n):
    values = list(range(n))
    left = 0
    right = n - 1
    swaps = 0
    while left < right:
        values[left], values[right] = values[right], values[left]
        swaps += 1
        left += 1
        right -= 1
    return swaps

for n in [4, 8, 16]:
    print('n =', n, 'swaps:', swaps_needed(n))

Edge cases and pitfalls

An empty list has no pair to swap. A single value is already reversed. The loop condition left < right handles both cases without a special branch.

The common mistake is stepping only one index. The pair then swaps the wrong cells, and one end is visited twice. Both indices must step after every swap.

Edge cases, run

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

print('empty:', reverse_in_place([]))
print('single:', reverse_in_place([7]))
print('even:', reverse_in_place([1, 2, 3, 4]))
print('odd:', reverse_in_place([1, 2, 3]))
print('duplicates:', reverse_in_place([2, 2, 1]))

Exercise

How many swaps reverse a list of 7 values in place?