Description:
Write a function that takes a string as input and reverse only the vowels of a string.
Example 1:
Given s = “hello”, return “holle”.
Example 2:
Given s = “leetcode”, return “leotcede”.
Note:
The vowels does not include the letter “y”.
解法一:
基本思想:set的使用,对撞指针。
思路:将元音字母存入set中,利用set的.find()方法,返回的是找到的元素的下标,否则返回.end()。对撞指针用于从头从尾找到元音然后进行swap。
Time: O(n^2)
Space: O(1)
class Solution {
public:
string reverseVowels(string s) {
if(s.size() == 0)
return s;
set<char> vowels = {'A','E','I','O','U','a','e','i','o','u'}; //因为无需排序,可以直接用unordered_set
int i = 0, j = s.size() - 1;
while(i < j){
while(vowels.find(s[i])==vowels.end()) //set的find()时间复杂度O(logn), unordered_set的find()时间复杂度O(1)
i++;
while(vowels.find(s[j])==vowels.end())
j--;
if(i >= j) //注意是>=,不是==,如果是i==j则有可能在swap过一次以后,i遍历到原j位置,j遍历到原i位置,然后又swap回来了,此时i>j
break;
if(s[i]!=s[j])
swap(s[i],s[j]);//对于都是元音时,不论是否swap,都要i++,j--,因此i++,j--不能写在括号里
i++;
j--;
}
return s;
}
};
算法细节:
- 在判断i,j是否相遇时,不能写
if(i==j)
,要写if(i>=j)
,这是因为有可能i,j直接跨越了等于的条件,直接变成i>j,如在“hello”的输入中,元音第一次交换,变成“holle”,然后i到达了j原来的位置,j到达了i原来的位置,此时i不等于j,i>j,如果是if(i==j)
那么它们又会换回来,最终输出“hello”,这是有问题的。 - 在存元音到set中时,由于可以是无序的,那么可以使用unordered_set来存。set的find函数时间复杂度O(logn)(底层采用平衡树),而unordered_set的查找函数.find()时间复杂度是O(1)。(底层采用哈希表)
- 注意swap完之后的i++,j–不能写在中括号中间,因为判断两个元音是否相等是为了减少unnecessary swap,不管这两个元音是否swap,都要继续前进,也就是i++,j–
解法二:
基本思想:巧用ASCII范围。
class Solution {
public:
string reverseVowels(string s) {
int dict[256] = {0};
dict['a'] = 1, dict['A'] = 1;
dict['e'] = 1, dict['E'] = 1;
dict['i'] = 1, dict['I'] = 1;
dict['o'] = 1, dict['O'] = 1;
dict['u'] = 1, dict['U'] = 1;
int i = 0, j = (int)s.size() - 1;
while(i < j){
while(i < j && dict[s[i]] == 0) i++;
while(i < j && dict[s[j]] == 0) j--;
swap(s[i],s[j]);
i++;j--;
}
return s;
}
};
算法细节:
- 同样注意swap完之后的i++,j–不能写在中括号中间,因为判断两个元音是否相等是为了减少unnecessary swap,不管这两个元音是否swap,都要继续前进,也就是i++,j–