Leetcode 原题链接
解法一
这道题很简单,令双指针 l l l 和 r r r 从两侧相向移动,交换元音字母即可。但大多人的实现是如下这种可简化的嵌套循环。
如果是 Java 等 String 不可变的语言,应先转换为 CharArray,交换完元音字母后改回 String 形式。
此处仅提供 Java 代码,多语言代码块可以看这里。
class Solution {
public String reverseVowels(String s) {
int l = 0; // 左指针
int r = s.length() - 1; // 右指针
// 将字符串 s 改成数组,方便交换字符
char[] chars = s.toCharArray();
// 所有元音字母,hash set 形式
Set<Character> vowels = new HashSet<>(Arrays.asList('a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U'));
while (l < r) {
// 从左向右找元音字母
while (l < s.length() && !vowels.contains(chars[l]))
l++;
// 从右向左找元音字母
while (r >= 0 && !vowels.contains(chars[r]))
r--;
// 双指针相遇,退出
if (l >= r) break;
// 交换
char temp = chars[l];
chars[l++] = chars[r];
chars[r--] = temp;
}
return new String(chars);
}
}
解法二
我们可以在一个循环中直接实现。
class Solution {
public String reverseVowels(String s) {
int l = 0;
int r = s.length() - 1;
char[] chars = s.toCharArray();
Set<Character> vowels = new HashSet<>(Arrays.asList('a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U'));
while (l < r) {
if (!vowels.contains(chars[l])) {
l++;
} else if (!vowels.contains(chars[r])) {
r--;
} else {
char temp = chars[l];
chars[l] = chars[r];
chars[r] = temp;
l++;
r--;
}
}
return new String(chars);
}
}
这种简化循环的技巧在实际开发中也能用到,只是稍慢于传统的嵌套 while
循环。
读者在初次接触时可能不太习惯,但一回生,二回熟。
复杂度
时间:
Θ
(
n
)
\Theta(n)
Θ(n)
空间:
- 在 C++ 等 String 可变的语言中为 Θ ( 1 ) \Theta(1) Θ(1)
- 在其他语言中因为构建了数组,为 Θ ( n ) \Theta(n) Θ(n)
推广
以下均为个人所著,兼顾了面试、本科、硕士阶段,包含清晰的 PPT 动画展示以及配套的练习题。读者也在陆续写其他算法教程。
-
附个人题解的双指针题单
-
图论入门
-
图论进阶