这是我参与8月更文挑战的第19天,活动详情查看:8月更文挑战
前言
今天又是算法日,(其实是因为平时做不出来~做出来的那天就有发了)。>/br? 好的,今天又是简单题日,开冲!!!!!!!
题目
编写一个函数,以字符串作为输入,反转该字符串中的元音字母。
- 示例 1:
输入: "hello"
输出: "holle"
- 示例 2:
输入: "leetcode"
输出: "leotcede"
题外话
一般有些算法题看不太懂,先不要去搜或者直接看解析,如果连题目都读不懂,就放弃,这属实有点可惜。所以可以尝试看看英文版,毕竟大部分的算法题都是直译过来的(原创除外);看看英文版,很多坑+问题疑惑就会迎刃而解~
Given a string s, reverse only all the vowels in the string and return it.
The vowels are 'a', 'e', 'i', 'o', and 'u', and they can appear in both cases.
Constraints:
1 <= s.length <= 3 * 105sconsist of printable ASCII characters.
逻辑思路
- 看了英文版是不是有种阔然开朗的感觉,本来对于元音字母还有点模糊~现在直接知道了 → 'a', 'e', 'i', 'o','u';
- 雷点远远不止这里,英文版的敲重点来了 → ASCII,这意味着除了小写,还需要大写;
- 排雷完毕,就是解析思路了:
- 一个字符串拆解成char[]的数组
- 利用双指针方法,从首末分别相向遍历,直至相遇,把分别遇到的元音作为交换;
- 判断当前字符是否符合元音 → 采用String.indexOf方法,存在返回首次遇到下标,不存在则返回-1
实现
- 解析元音采用indexOf方法,比较简单粗暴
class Solution {
public String reverseVowels(String s) {
char[] a = s.toCharArray();
int n = a.length;
int i = 0;
int j = n-1;
while (j>i){
while (i<n && !change(a[i])){
++i;
}
while (j>0 && !change(a[j])){
--j;
}
if(j>i){
char c = a[i];
a[i] = a[j];
a[j] = c;
++i;
--j;
}
}
return new String(a);
}
public boolean change(char ch){
return "AEIOUaeiou".indexOf(ch)>=0;
}
}
官方题解
我们可以使用两个指针 ii 和 jj 对字符串相向地进行遍历。
具体地,指针 ii 初始时指向字符串 ss 的首位,指针 jj 初始时指向字符串 ss 的末位。在遍历的过程中,我们不停地将 ii 向右移动,直到 ii 指向一个元音字母(或者超出字符串的边界范围);同时,我们不停地将 jj 向左移动,直到 jj 指向一个元音字母。此时,如果 i<ji<j,那么我们交换 ii 和 jj 指向的元音字母,否则说明所有的元音字母均已遍历过,就可以退出遍历的过程。
复杂度分析
-
时间复杂度:O(n),其中 n 是字符串 s 的长度。在最坏的情况下,两个指针各遍历整个字符串一次。
-
空间复杂度:O(1) 或 O(n),取决于使用的语言中字符串类型的性质。如果字符串是可修改的,那么我们可以直接在字符串上使用双指针进行交换,空间复杂度为O(1),否则需要使用 O(n) 的空间将字符串临时转换为可以修改的数据结构(例如数组),空间复杂度为O(n)。