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
mathjust 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)