Skip to content

344. Reverse String

On LeetCode ->

Reformulated question

Reverse a list of characters in-place, using \(O(1)\) extra space, and return nothing.

  • Example: ["h","e","l","l","o"] -> ["o","l","l","e","h"] because the same list must be mutated, not replaced.

Key trick

Use two pointers.

  • Start one at the left end and one at the right end.
  • Swap while left < right.
  • This reverses in-place with constant extra memory.

Trap

  • Returning a new reversed list instead of mutating the input.
  • Using slicing like s[::-1] without assigning back element-by-element, which is not the intended in-place idea.
  • Looping one step too far.
  • Using ceil(n / 2) is unnecessary and adds noise.

Why this question is interesting?

It checks whether you distinguish:

  • in-place mutation vs returning a new value
  • simple index reasoning
  • odd/even length boundary handling

Solve the problem with idiomatic Python

class Solution:
    def reverseString(self, s: list[str]) -> None:
        # Two pointers swapping toward the center.
        left, right = 0, len(s) - 1

        while left < right:
            s[left], s[right] = s[right], s[left]
            left += 1
            right -= 1

A Python-specific in-place alternative is:

class Solution:
    def reverseString(self, s: list[str]) -> None:
        # Reverse the same list object in-place.
        s.reverse()

Pytest test

import pytest

@pytest.mark.parametrize(
    "chars, expected",
    [
        (["h", "e", "l", "l", "o"], ["o", "l", "l", "e", "h"]),
        (["H", "a", "n", "n", "a", "h"], ["h", "a", "n", "n", "a", "H"]),
        (["a"], ["a"]),
        (["a", "b"], ["b", "a"]),
        (["a", "b", "c"], ["c", "b", "a"]),
        (["1", " ", "!"], ["!", " ", "1"]),
    ],
)
def test_reverse_string(chars, expected):
    Solution().reverseString(chars)
    assert chars == expected

Comment my solution

Your solution is correct, but a bit more complicated than needed.

  • math.ceil(l / 2) is unnecessary.
  • Importing math just for this is avoidable.
  • Python tuple-swap is cleaner than a temporary variable.
## Solution

import math

class Solution:
    def reverseString(self, s: list[str]) -> None:
        """
        Do not return anything, modify s in-place instead.
        """

        l = len(s)
        for i in range(0, math.ceil(l / 2)):
            tmp = s[i]
            s[i] = s[l - 1 - i]
            s[l - 1 - i] = tmp

## Test

@pytest.mark.parametrize(
    "s,s_reversed",
    [
        (["h", "e", "l", "l", "o"], ["o", "l", "l", "e", "h"]),
        (["H", "a", "n", "n", "a", "h"], ["h", "a", "n", "n", "a", "H"]),
    ],
)
def test_reverse_string(s, s_reversed):
    solver = Solution()
    solver.reverseString(s)

    assert s == s_reversed

A more idiomatic version of your approach is:

class Solution:
    def reverseString(self, s: list[str]) -> None:
        n = len(s)
        for i in range(n // 2):
            s[i], s[n - 1 - i] = s[n - 1 - i], s[i]

Code

import pytest


class Solution:
    def reverseString(self, s: list[str]) -> None:
        # Two pointers swapping toward the center.
        left, right = 0, len(s) - 1
        while left < right:
            s[left], s[right] = s[right], s[left]
            left += 1
            right -= 1


class SolutionReverseMethod:
    def reverseString(self, s: list[str]) -> None:
        # Built-in in-place reverse.
        s.reverse()


@pytest.mark.parametrize(
    "chars, expected",
    [
        (["h", "e", "l", "l", "o"], ["o", "l", "l", "e", "h"]),
        (["H", "a", "n", "n", "a", "h"], ["h", "a", "n", "n", "a", "H"]),
        (["a"], ["a"]),
        (["a", "b"], ["b", "a"]),
        (["a", "b", "c"], ["c", "b", "a"]),
        (["1", " ", "!"], ["!", " ", "1"]),
    ],
)
def test_reverse_string(chars, expected):
    Solution().reverseString(chars)
    assert chars == expected


s = ["h", "e", "l", "l", "o"]
Solution().reverseString(s)
print(s)

t = ["H", "a", "n", "n", "a", "h"]
SolutionReverseMethod().reverseString(t)
print(t)