Reverse Only the Vowels of a String
Solve this Problems, reverse only the vowels in it and return the result — every consonant stays exactly where it is.
Collecting every vowel into a separate list and handing them back out in reverse order works, but it costs an extra list the size of the vowel count. The two-pointerTwo PointerUsing two indices that move through one or more sequences to avoid redundant re-scanning. technique swaps vowels directly in place: walk pointers inward from both ends, sliding each one forward or backward until it lands on a vowel, then swap the pair and keep going. No extra storage is needed — the vowels trade positions as the pointers move toward the middle.
Test Case 1:
Test Case 2:
Test Case 3:
Constraints
- ◆
1 ≤ s.length ≤ 3 × 10⁵ - ◆
s consists of printable ASCII characters
Try the Dry Run
Don't just read the solution — watch it execute, one step at a time.
| 1 | class Solution { |
| 2 | public String reverseOnlyVowels(String s) { |
| 3 | char[] chars = s.toCharArray(); |
| 4 | int left = 0, right = chars.length - 1; |
| 5 | while (left < right) { |
| 6 | while (left < right && !isVowel(chars[left])) left++; |
| 7 | while (left < right && !isVowel(chars[right])) right--; |
| 8 | if (left < right) { |
| 9 | char temp = chars[left]; |
| 10 | chars[left] = chars[right]; |
| 11 | chars[right] = temp; |
| 12 | left++; |
| 13 | right--; |
| 14 | } |
| 15 | } |
| 16 | return new String(chars); |
| 17 | } |
| 18 | private boolean isVowel(char c) { |
| 19 | return "aeiouAEIOU".indexOf(c) != -1; |
| 20 | } |
| 21 | } |
| 22 |
04Set left to 0 and right to the last index, 4.
Approach & Solutions
Brute Force — Collect, Then Rebuild
BruteWalk the string once to collect every vowel into a separate list, in the order they appear. Then walk the string a second time, and for every position that holds a vowel, pull the next one off the *end* of that collected list (which puts them back in reverse order); every consonant is copied through unchanged. Correct, but it needs an extra list the size of the vowel count just to remember them.
O(n)O(n)1class Solution {
2 public String reverseOnlyVowels(String s) {
3 Deque<Character> vowels = new ArrayDeque<>();
4 for (char c : s.toCharArray()) {
5 if (isVowel(c)) vowels.addLast(c);
6 }
7 StringBuilder result = new StringBuilder();
8 for (char c : s.toCharArray()) {
9 if (isVowel(c)) result.append(vowels.pollLast());
10 else result.append(c);
11 }
12 return result.toString();
13 }
14 private boolean isVowel(char c) {
15 return "aeiouAEIOU".indexOf(c) != -1;
16 }
17}Optimal — Two Pointers, In Place
OptimalSkip the second list entirely. Walk two pointers inward from both ends of the string. At each step, slide the left pointer forward until it lands on a vowel, and slide the right pointer backward until it lands on a vowel, then swap the two characters directly. No extra list is needed — the vowels swap into place as the pointers meet in the middle.
O(n)O(1) extra1class Solution {
2 public String reverseOnlyVowels(String s) {
3 char[] chars = s.toCharArray();
4 int left = 0, right = chars.length - 1;
5 while (left < right) {
6 while (left < right && !isVowel(chars[left])) left++;
7 while (left < right && !isVowel(chars[right])) right--;
8 if (left < right) {
9 char temp = chars[left];
10 chars[left] = chars[right];
11 chars[right] = temp;
12 left++;
13 right--;
14 }
15 }
16 return new String(chars);
17 }
18 private boolean isVowel(char c) {
19 return "aeiouAEIOU".indexOf(c) != -1;
20 }
21}