Home
DSA Patterns
Two Pointers
Reverse Vowels of a String
Reverse Vowels of a String
Reverse the order of the vowels in a string while every consonant stays in place, using two pointers that skip consonants and swap vowels.
Problem Understanding
Reverse Vowels of a String (LeetCode 345): given a string s, reverse only its vowels and return the result. The vowels are a, e, i, o and u, in lower and upper case; every other character keeps its position.
Examples: "IceCreAm" → "AceCreIm"; "leetcode" → "leotcede".
The Intuition: Reverse a String, but Skip the Consonants
Reversing a whole string swaps the outermost pair and works inward. Here, do the same, but treat consonants as if they were not there.
- Two pointers at the two ends.
- Skip any consonant on either side.
- Swap when both pointers are on vowels, then move both inward.
It is Valid Palindrome's skip-what-does-not-count loop, with a swap where that lesson compares.
Interactive Walkthrough
CONSONANTS NEVER MOVE
l = 0, r = n − 1
s (vowels tinted)
l
0
1
2
3
4
5
6
r
7
l
0
r
7
Swaps
0
l starts at index 0 and r at index 7
Next
'm' at 7 is not a vowel: move r left to 6
s
Vowels are tinted so you can see where l and r will stop. Consonants never move. Swapped vowels turn green. Try Case to see upper and lower case treated alike.
Dry Run Table
Input: s = "IceCreAm".
| l | r | Action | String |
|---|---|---|---|
| 0 (I) | 7 (m) | r is a consonant: r = 6 | IceCreAm |
| 0 (I) | 6 (A) | swap | AceCreIm |
| 1 (c) | 5 (e) | l is a consonant: l = 2 | AceCreIm |
| 2 (e) | 5 (e) | swap | AceCreIm |
| 3 (C) | 4 (r) | l is a consonant: l = 4, pointers meet | AceCreIm |
Answer: "AceCreIm".
The Solution Template
Two pointers over a character array; a vowel set makes each check O(1).
Reverse Vowels of a String Code
1var reverseVowels = function(s) {2 const vowels = new Set('aeiouAEIOU');3 const chars = [...s];4 let l = 0, r = chars.length - 1;5 while (l < r) {6 if (!vowels.has(chars[l])) {7 l++;8 } else if (!vowels.has(chars[r])) {9 r--;10 } else {11 [chars[l], chars[r]] = [chars[r], chars[l]];12 l++;13 r--;14 }15 }16 return chars.join('');17};
Edge Cases & Common Mistakes
- Uppercase vowels: include A, E, I, O, U.
- No vowels: l walks to r without swapping; the string is unchanged.
- One vowel: nothing to swap it with, so it stays.
- Moving both pointers on a skip: only the pointer on the consonant should move, or you can step past a vowel.
Summary
Two pointers from both ends: skip consonants, swap vowels, move inward until they meet. O(n) time, O(n) space for the character array (O(1) in C and C++).
More practice: DSA interview questions with answers · patterns cheat sheet
