Easy
题目描述
给定一个字符串 s,仅反转字符串中的元音字母并返回。
元音字母包括 'a'、'e'、'i'、'o'、'u',它们可以以大小写形式出现,且可能出现多次。
示例 1:
输入:s = "IceCreAm"
输出:"AceCreIm"
解释:s 中的元音字母为 ['I', 'e', 'e', 'A']。反转这些元音字母后,s 变成 "AceCreIm"。
示例 2:
输入:s = "leetcode"
输出:"leotcede"
提示:
1 <= s.length <= 3 * 10^5s由可打印的 ASCII 字符组成
解题思路
这道题可以使用双指针技巧来解决。核心思想是用两个指针分别从字符串的首尾开始,向中间移动,找到元音字母时进行交换。
解题思路:
双指针法(推荐): 设置左右两个指针,分别从字符串开头和结尾开始。左指针向右移动寻找元音字母,右指针向左移动寻找元音字母。当两个指针都找到元音字母时,交换它们的位置,然后继续移动指针,直到两指针相遇。
先收集再反转: 也可以先遍历一遍字符串收集所有元音字母,将它们反转后再重新放回原位置。但这种方法需要额外的空间存储元音字母。
实现细节:
- 需要判断字符是否为元音字母,包括大小写
- 使用集合或字符串查找来快速判断元音字母
- 注意字符串在某些语言中是不可变的,需要转换为字符数组进行操作
双指针法的时间复杂度为 O(n),空间复杂度为 O(1)(除了输出所需的空间),是最优解法。
代码实现
class Solution {
public:
string reverseVowels(string s) {
string vowels = "aeiouAEIOU";
int left = 0, right = s.length() - 1;
while (left < right) {
while (left < right && vowels.find(s[left]) == string::npos) {
left++;
}
while (left < right && vowels.find(s[right]) == string::npos) {
right--;
}
if (left < right) {
swap(s[left], s[right]);
left++;
right--;
}
}
return s;
}
};
class Solution:
def reverseVowels(self, s: str) -> str:
vowels = set('aeiouAEIOU')
s_list = list(s)
left, right = 0, len(s) - 1
while left < right:
while left < right and s_list[left] not in vowels:
left += 1
while left < right and s_list[right] not in vowels:
right -= 1
if left < right:
s_list[left], s_list[right] = s_list[right], s_list[left]
left += 1
right -= 1
return ''.join(s_list)
public class Solution {
public string ReverseVowels(string s) {
HashSet<char> vowels = new HashSet<char> {'a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U'};
char[] chars = s.ToCharArray();
int left = 0, right = s.Length - 1;
while (left < right) {
while (left < right && !vowels.Contains(chars[left])) {
left++;
}
while (left < right && !vowels.Contains(chars[right])) {
right--;
}
if (left < right) {
char temp = chars[left];
chars[left] = chars[right];
chars[right] = temp;
left++;
right--;
}
}
return new string(chars);
}
}
var reverseVowels = function(s) {
const vowels = new Set(['a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U']);
const chars = s.split('');
let left = 0, right = s.length - 1;
while (left < right) {
while (left < right && !vowels.has(chars[left])) {
left++;
}
while (left < right && !vowels.has(chars[right])) {
right--;
}
if (left < right) {
[chars[left], chars[right]] = [chars[right], chars[left]];
left++;
right--;
}
}
return chars.join('');
};
复杂度分析
| 复杂度类型 | 复杂度 | 说明 |
|---|---|---|
| 时间复杂度 | O(n) | 需要遍历字符串一次,每个字符最多被访问一次 |
| 空间复杂度 | O(1) | 只使用常数额外空间(不包括输出字符串所需空间) |
相关题目
. Reverse String (Easy)
. Faulty Keyboard (Easy)
. Sort Vowels in a String (Medium)