Date: 2026-06-06
Time: 18:54
This file implements LeetCode 345 — Reverse Vowels of a String. It owns a single responsibility: given a string, return a new string where only the vowel characters have their positions reversed, while all non-vowel characters stay in place.
It lives under reverse-vowels-of-a-string/solution.py following the repo's convention of one problem per directory with solution.py, test_solution.py, plan.md, and review.md.
Solution.reverseVowels(self, s: str) -> strThe only method. Contract:
s of printable ASCII characters (per LeetCode constraints, 1 <= len(s) <= 3 * 10^5).vowels constant (local)set("aeiouAEIOU") — a set of 10 characters covering both cases. Using a set gives O(1) membership testing instead of O(10) linear scan on a string.
Two-pointer inward sweep. left starts at 0, right at the last index. Both march inward:
left points to a non-vowel, advance it.right points to a non-vowel, retreat it.This is the canonical in-place two-pointer pattern for "reverse a subset of elements." It's the same structure used in reverse-only-letters/solution.py (swap letters, skip non-letters).
Mutable list copy. Python strings are immutable, so the string is converted to list(s) for O(1) swaps, then joined back at the end. This avoids O(n^2) string concatenation.
Imports: none — the solution is self-contained with no stdlib or third-party imports.
Imported by: reverse-vowels-of-a-string/test_solution.py directly. The "Imported By" list in the prompt is misleading — those are all test files across the repo that import their *own* solution.py, not this one. The actual consumer is only the local test file.
1. Build a set of vowel characters (both cases).
2. Convert s to a mutable chars list.
3. Initialize left = 0, right = len(chars) - 1.
4. Loop while left < right:
5. Join and return.
Each character is visited at most once by each pointer, so the total work is O(n) time, O(n) space (for the list copy).
while left < right guard ensures no double-swaps and no out-of-bounds access. When left >= right, the string is fully processed.elif/else branching guarantees a pointer only advances past a character when it's confirmed as a non-vowel, or after a swap is performed.None. The method assumes valid input per LeetCode constraints. An empty string or single-character string works correctly — the while loop simply never executes, and "".join(chars) returns the original string.
reverse-only-letters/solution.py — Uses the identical two-pointer-skip pattern but for letters vs. non-letters; compare the swap predicatesreverse-vowels-of-a-string/test_solution.py — See which edge cases are covered (empty, all vowels, no vowels, mixed case)two-pointer-inward-sweep — This pattern recurs in valid-palindrome, squares-of-a-sorted-array, two-sum (sorted variant); worth cataloging as a cross-cutting techniqueremove-vowels-from-a-string/solution.py — The complement problem (remove vowels entirely); compare the vowel-set usagedetermine-if-string-halves-are-alike/solution.py — Another vowel-counting problem; see how the vowel set is defined therereverse-vowels-two-pointer-time — reverseVowels runs in O(n) time because each pointer advances monotonically and they collectively cover the string oncereverse-vowels-case-sensitive-set — The vowel set includes both uppercase and lowercase variants, so the solution handles mixed-case input without normalizationreverse-vowels-non-vowel-stability — Non-vowel characters are never moved; only characters at positions where both pointers point to vowels are swappedreverse-vowels-no-imports — The solution has zero imports and depends only on Python builtins (set, list, str.join)