Pattern: Two Pointers → opposite ends
Difficulty: Easy
Time: O(n) | Space: O(n) for the char array (JS strings are immutable)
Problem
Reverse only the vowels in a string. Everything else stays where it is.
Vowels are a e i o u, upper and lower case.
"IceCreAm" → "AceCreIm"
"leetcode" → "leotcede"
Core idea
One pointer at each end. Each walks inward until it lands on a vowel. Swap, then keep going.
lstarts at 0,rat the end.- Move
lright until it’s on a vowel. - Move
rleft until it’s on a vowel. - Swap them, move both inward.
- Stop when they meet.
It’s a normal string reverse, except each pointer skips the letters you don’t care about.
Code (TypeScript)
function reverseVowels(s: string): string {
const vowels = new Set("aeiouAEIOU");
const chars = s.split(""); // strings can't be changed, arrays can
let l = 0;
let r = chars.length - 1;
while (l < r) {
while (l < r && !vowels.has(chars[l])) l++; // find a vowel from the left
while (l < r && !vowels.has(chars[r])) r--; // find a vowel from the right
[chars[l], chars[r]] = [chars[r], chars[l]];
l++;
r--;
}
return chars.join("");
}Gotchas
- Uppercase vowels count.
"IceCreAm"fails if you only check lowercase. - Every inner
whileneedsl < rfirst, or the pointers can run past each other. - A
Setlookup is O(1)."aeiou".includes(c)also works and is fine for 10 letters. - JS strings are immutable, so
s[l] = ...silently does nothing. Split into an array first. - Test: no vowels (
"bcd"), one letter, all vowels, mixed case.
Cues that said “two pointers”
- The word reverse → swap position
lwith positionr. - Only some items take part → each pointer skips until it finds one.
Related
- Two Pointers → opposite ends
- Reverse Words in a String (LC 151) is next in LeetCode 75
- Reverse String (LC 344) is the same template with no skipping