Medium
题目描述
给定一个下标从 0 开始的字符串 s,重新排列 s 中的字符得到新字符串 t,使得:
- 所有辅音字母都保持在原来的位置上。更正式地说,如果满足 0 <= i < s.length 的下标 i 处的 s[i] 是辅音字母,那么 t[i] = s[i]。
- 元音字母必须按照其 ASCII 值的非递减顺序排序。更正式地说,对于满足 0 <= i < j < s.length 且 s[i] 和 s[j] 都是元音字母的下标对 i,j,那么 t[i] 的 ASCII 值不能高于 t[j] 的 ASCII 值。
返回结果字符串。
元音字母是 ‘a’、’e’、‘i’、‘o’ 和 ‘u’,它们可以是小写或大写形式。辅音字母是所有不是元音字母的字母。
示例 1:
输入:s = "lEetcOde"
输出:"lEOtcede"
解释:'E'、'O' 和 'e' 是 s 中的元音字母;'l'、't'、'c' 和 'd' 都是辅音字母。元音字母按照其 ASCII 值排序,辅音字母保持在相同的位置。
示例 2:
输入:s = "lYmpH"
输出:"lYmpH"
解释:s 中没有元音字母(s 中的所有字符都是辅音字母),所以我们返回 "lYmpH"。
提示:
- 1 <= s.length <= 10^5
- s 只包含英文字母的大写和小写形式
解题思路
这道题要求我们对字符串中的元音字母按ASCII值排序,同时保持辅音字母的原始位置不变。
解题思路:
- 提取元音字母:遍历字符串,找出所有元音字母(包括大小写的a、e、i、o、u)
- 排序元音字母:将提取的元音字母按ASCII值从小到大排序
- 重构字符串:再次遍历原字符串,遇到辅音字母直接保留,遇到元音字母则按顺序替换为排序后的元音字母
算法步骤:
- 首先定义一个函数来判断字符是否为元音字母
- 遍历字符串收集所有元音字母到数组中
- 对元音字母数组进行排序
- 使用双指针技巧,重新遍历原字符串,用排序后的元音字母逐个替换原来的元音字母位置
这种方法时间复杂度主要取决于排序操作和两次遍历,空间复杂度取决于元音字母的数量。
代码实现
class Solution {
public:
string sortVowels(string s) {
auto isVowel = [](char c) {
return c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u' ||
c == 'A' || c == 'E' || c == 'I' || c == 'O' || c == 'U';
};
vector<char> vowels;
for (char c : s) {
if (isVowel(c)) {
vowels.push_back(c);
}
}
sort(vowels.begin(), vowels.end());
int vowelIndex = 0;
for (int i = 0; i < s.length(); i++) {
if (isVowel(s[i])) {
s[i] = vowels[vowelIndex++];
}
}
return s;
}
};
class Solution:
def sortVowels(self, s: str) -> str:
def is_vowel(c):
return c in 'aeiouAEIOU'
vowels = [c for c in s if is_vowel(c)]
vowels.sort()
result = []
vowel_index = 0
for c in s:
if is_vowel(c):
result.append(vowels[vowel_index])
vowel_index += 1
else:
result.append(c)
return ''.join(result)
public class Solution {
public string SortVowels(string s) {
bool IsVowel(char c) {
return "aeiouAEIOU".Contains(c);
}
var vowels = new List<char>();
foreach (char c in s) {
if (IsVowel(c)) {
vowels.Add(c);
}
}
vowels.Sort();
var result = new char[s.Length];
int vowelIndex = 0;
for (int i = 0; i < s.Length; i++) {
if (IsVowel(s[i])) {
result[i] = vowels[vowelIndex++];
} else {
result[i] = s[i];
}
}
return new string(result);
}
}
var sortVowels = function(s) {
const isVowel = (c) => 'aeiouAEIOU'.includes(c);
const vowels = [];
for (const c of s) {
if (isVowel(c)) {
vowels.push(c);
}
}
vowels.sort();
const result = [];
let vowelIndex = 0;
for (const c of s) {
if (isVowel(c)) {
result.push(vowels[vowelIndex++]);
} else {
result.push(c);
}
}
return result.join('');
};
复杂度分析
| 复杂度类型 | 分析 |
|---|---|
| 时间复杂度 | O(n log k),其中 n 是字符串长度,k 是元音字母数量。需要遍历字符串两次 O(n),排序元音字母 O(k log k) |
| 空间复杂度 | O(k),其中 k 是元音字母数量,用于存储提取的元音字母数组 |
相关题目
- . Reverse Vowels of a String (Easy)