LeetCode 345. 反转字符串中的元音字母
题目描述

题意分析
只将字符串中所有元音的出现次序反转,其他字符仍留在原下标。元音包括
a、e、i、o、u及对应大写形式;大小写是字符自身的一部分,移动时原样保留,不统一转换。返回新的字符串。题目输入是可打印 ASCII 字符,数字、标点以及其他字母都不能当作元音;没有元音或只有一个元音时,结果与输入相同。
解法:左右指针交换元音
核心思路
[!blue]
如果只看元音组成的序列,反转就是交换第一与最后一个、第二与倒数第二个。无需先提取这条序列,可以直接在原位置上用左右指针寻找下一对需要交换的元音。
左指针向右跳过非元音,右指针向左跳过非元音,停下时分别指向最左与最右尚未处理的元音。只要它们仍是两个不同位置,就交换这两个字符,再同时向内推进。
每轮结束后,两个指针外侧的元音都已处于最终顺序,后面不会再碰到;非元音从未参与写入,因此位置不变。指针相遇或交错时,最多剩下一个居中的元音,无需移动,整个反转就完成了。
输入字符串不可变,Java 先转成
char[]、Go 先转成字节切片,在可写缓冲区交换后再构造字符串。每次寻找都先检查left < right,避免整段没有元音时越过边界。
解题步骤
- 复制到可修改字符缓冲区,将两个指针放在首尾。
- 左指针跳过非元音,右指针也跳过非元音,两次寻找都受
left < right限制。- 两指针仍未相遇时交换它们指向的元音,再向内移动。
- 不再有需要交换的元音对时,将缓冲区转回字符串返回。
代码实现
class Solution {
// 左右指针分别向中间寻找下一个元音,两个指针都停在元音上时再交换。
public String reverseVowels(String s) {
char[] chars = s.toCharArray();
int left = 0;
int right = chars.length - 1;
// 两端之外的元音已就位,非元音位置始终不改动
while (left < right) {
while (left < right && !isVowel(chars[left])) {
left++;
}
while (left < right && !isVowel(chars[right])) {
right--;
}
if (left < right) {
char swapValue = chars[left];
chars[left] = chars[right];
chars[right] = swapValue;
}
left++;
right--;
}
return new String(chars);
}
private boolean isVowel(char ch) {
return "aeiouAEIOU".indexOf(ch) >= 0;
}
}
func reverseVowels(s string) string {
// 左右指针分别向中间寻找下一个元音,两个指针都停在元音上时再交换。
chars := []byte(s)
left, right := 0, len(chars)-1
// 两端之外的元音已就位,非元音位置始终不改动
for left < right {
for left < right && !isVowel(chars[left]) {
left++
}
for left < right && !isVowel(chars[right]) {
right--
}
if left < right {
chars[left], chars[right] = chars[right], chars[left]
}
left++
right--
}
return string(chars)
}
func isVowel(ch byte) bool {
switch ch {
case 'a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U':
return true
default:
return false
}
}
复杂度分析
- 时间复杂度:$O(n)$,每个指针单向移动。
- 空间复杂度:$O(n)$,字符缓冲与结果转换。
关键点总结
[!green]
- 交换发生在元音位置之间,其他位置不动。
- 大小写字符各自保留原字符,不做统一转小写。
易错点总结
[!yellow]
- 只识别小写会遗漏大写元音;为便于判断而直接把输出全部转小写,也会改变原字符。
- 元音仅为指定的十个字符,不能把标点、数字等所有非辅音都当作元音。
- 跳过非元音时也要检查指针边界,不能只在最外层检查。
- 只能交换找到的元音位置,直接反转整个区间会移动本应保持原位的其他字符。
相似题目
| 题目 | 难度 | 关联与区别 |
|---|---|---|
| 344. 反转字符串 | 简单 | 同样由两端交换,本题先跳过非元音,只对符合条件的位置配对。 |
| 917. 仅仅反转字母 | 简单 | 同样仅反转某类字符,原题保留非字母位置,本题保留非元音位置。 |
转载与许可
许可
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!