LeetCode 345简单双指针/字符串
反转字符串中的元音 图解题解
这道题到底在问什么
给定字符串 s,只反转其中的元音字母(位置首尾对称交换),非元音保持原位,返回结果。
- 输入
- s="hello"
- 输出
- "holle"(e、o 交换)
- 输入
- s="leetcode"
- 输出
- "leotcede"
最优解:一步一步想明白
- 3记住「l 找元音、r 找元音、交换、各进一格」,下面每帧都在套它。
- 4开局:l 指最左、r 指最右。两个指针向中间逼近,各自找元音。
- 5看 l=0 的 'q',不是元音,l 向右移一格继续找。
- 6l=1 的 'u' 是元音(红色),l 停下,等右边也找到元音再交换。
- 7r=11 的 'e' 也是元音(红色)。现在 l、r 两端都停在元音上,可以交换了。
- 8l、r 都停在元音上了('u' 和 'e',红色),把它们交换。
- 9交换完成(绿色):'u' 和 'e' 换了位。l、r 各往里走一格,继续找下一对元音。
- 10l=2 的 'e' 是元音(红色),l 停下,等右边也找到元音再交换。
- 11看 r=10 的 'l',不是元音,r 向左移一格继续找。
- 12看 r=9 的 'b',不是元音,r 向左移一格继续找。
- 13r=8 的 'a' 也是元音(红色)。现在 l、r 两端都停在元音上,可以交换了。
- 14l、r 都停在元音上了('e' 和 'a',红色),把它们交换。
- 15交换完成(绿色):'e' 和 'a' 换了位。l、r 各往里走一格,继续找下一对元音。
- 16看 l=3 的 's',不是元音,l 向右移一格继续找。
- 17看 l=4 的 't',不是元音,l 向右移一格继续找。
- 18l=5 的 'i' 是元音(红色),l 停下,等右边也找到元音再交换。
- 19看 r=7 的 'n',不是元音,r 向左移一格继续找。
- 20r=6 的 'o' 也是元音(红色)。现在 l、r 两端都停在元音上,可以交换了。
- 21l、r 都停在元音上了('i' 和 'o',红色),把它们交换。
- 22交换完成(绿色):'i' 和 'o' 换了位。l、r 各往里走一格,继续找下一对元音。
- 23l 和 r 相遇,所有元音都首尾对称换好了。最终结果:"qeastoineblu"。非元音字符自始至终没动过。
⚠️ 容易写错的地方
✗ 错:忘了大写元音 AEIOU
✓ 对:元音集合要含大小写
"AeRoUf" 里 A/e/o/U 都要参与反转
✗ 错:交换后忘了 l++、r−−
✓ 对:交换完两指针都要往里走
不移动会对同一对元音反复交换、死循环
✗ 错:内层循环没判 l < r
✓ 对:跳过非元音时也要守住 l < r
否则指针可能越过对方、越界
完整代码(Python / C++ / Java)
Python
class Solution:
def reverseVowels(self, s: str) -> str:
vowels = set('aeiouAEIOU')
arr = list(s)
l, r = 0, len(arr) - 1
while l < r:
while l < r and arr[l] not in vowels:
l += 1
while l < r and arr[r] not in vowels:
r -= 1
arr[l], arr[r] = arr[r], arr[l]
l += 1
r -= 1
return ''.join(arr)C++
#include <algorithm>
#include <string>
using namespace std;
class Solution {
public:
string reverseVowels(string s) {
string vowels = "aeiouAEIOU";
auto isV = [&](char c){ return vowels.find(c) != string::npos; };
int l = 0, r = (int)s.size() - 1;
while (l < r) {
while (l < r && !isV(s[l])) l++;
while (l < r && !isV(s[r])) r--;
swap(s[l++], s[r--]);
}
return s;
}
};Java
import java.util.*;
class Solution {
public String reverseVowels(String s) {
Set<Character> vowels = new HashSet<>(Arrays.asList('a','e','i','o','u','A','E','I','O','U'));
char[] arr = s.toCharArray();
int l = 0, r = arr.length - 1;
while (l < r) {
while (l < r && !vowels.contains(arr[l])) l++;
while (l < r && !vowels.contains(arr[r])) r--;
char tmp = arr[l]; arr[l++] = arr[r]; arr[r--] = tmp;
}
return new String(arr);
}
}复杂度
时间
O(n)
l、r 合计把字符串扫一遍
空间
O(1)
原地交换(转 char 数组不计)
看不够?换成动画再走一遍
上面的推演每一步都对应一帧动画。点开交互动画版,能一步步看着 反转字符串中的元音 的数据怎么变、指针怎么走,还能切 Python / Java / C++ 跟着练。
面试官可能追问
和「反转整个字符串」有何区别?+
反转整串是无条件交换 l、r;本题只在 l、r 都是元音时才交换,非元音要跳过、保持原位。多了「找元音」的内层循环,但仍是 O(n) 双指针。
y 算不算元音?+
本题按题目定义只算 a/e/i/o/u(含大写),y 不算。判定元音用一个集合即可,要不要含 y 取决于题目口径,务必按题面来。
想听吴师兄把这道题讲给你听?
文字版和动画都随便看。开通图解算法年卡,可以听吴师兄声线把 反转字符串中的元音 一步步讲透(全站 0 节语音精讲,持续扩充), 卡住的地方还有 AI 私教小欧就着动画帮你拆到懂。
本平台为独立第三方培训机构,与华为技术有限公司无任何关联;课程的服务内容与权益以购买协议为准,学习效果因个人情况而异。「华为 OD」「华为可信」等仅为对岗位与考试方向的客观描述,相关商标归各自权利人所有。