345.反转字符串中的元音字母
题目
原题链接
给你一个字符串 s
,仅反转字符串中的所有元音字母,并返回结果字符串。
元音字母包括 'a'
、'e'
、'i'
、'o'
、'u'
,且可能以大小写两种形式出现不止一次。
示例 1:
1 2
| 输入: s = "hello" 输出:"holle"
|
示例 2:
1 2
| 输入: s = "leetcode" 输出:"leotcede"
|
提示:
1 <= s.length <= 3 * 105
s
由 可打印的 ASCII 字符组成
双指针法
同样的,我们使用双指针来进行遍历:定义一个开始下标(一般为0),并定义一个结束下标(字符串长度-1)。我们使用 开始下标从头向尾遍历,结束下标从尾向头遍历,当开始下标大于结束下标时结束遍历。
思路分析
我们假设传入字符串为s,那么我们定义一个元音的字符集合 arr
,然后定义开始下标 start
和结束下标 end
,并将其同时对向遍历,并定义一个长度为 s.length()
的新数组 res
来接收反转后的字符,那么我们由此可得:
- 当
arr
不包含 s
在 start
下标时的字符,也就是 s
在 start
下标时的字符不是元音字符,那么 res[start]
的值为 s 在下标 start
时的值。
- 当上述条件不满足时,判断
arr
是否包含 s
在 end
下标时的字符,如果不包含说明 s
在 end
下标时的字符也不是元音字符,那么 res[end]
的值为 s 在下标 end
时的值。
- 如果以上条件均不满足,也就是说
s
在下标 start
下和 end
下时的字符均为原因字符,那么将其调换位置即可,即:res[start]
的值为 s
在 end
下标时的值,而 res[end]
的值为 s
在 start
下标时的值。
注意:题目中提到了字符可能会出现大小写,且不止一次,那么我们同样要对大小写字符进行归类比较。
图解
![未命名文件.gif](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
代码实现
实现一
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| public static String reverseVowels(String s) { List<Character> arr = Arrays.asList('a', 'e', 'i', 'o', 'u'); int start = 0; int end = s.length() - 1; char[] res = new char[s.length()]; while (start <= end) { char startChar = s.charAt(start); char endChar = s.charAt(end); if (!arr.contains(Character.toLowerCase(startChar)) && !arr.contains(Character.toLowerCase(endChar))) { res[start++] = startChar; res[end--] = endChar; } else if (!arr.contains(Character.toLowerCase(startChar)) && arr.contains(Character.toLowerCase(endChar))) { res[start++] = startChar; } else if (arr.contains(Character.toLowerCase(startChar)) && !arr.contains(Character.toLowerCase(endChar))) { res[end--] = endChar; } else { res[start++] = endChar; res[end--] = startChar; } } return new String(res); }
|
实现二
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| public String reverseVowels(String s) { HashSet<Character> vowels = new HashSet<>(Arrays.asList('a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U')); if (s == null) return null; int i = 0, j = s.length() - 1; char[] result = new char[s.length()]; while (i <= j) { char ci = s.charAt(i); char cj = s.charAt(j); if (!vowels.contains(ci)) { result[i++] = ci; } else if (!vowels.contains(cj)) { result[j--] = cj; } else { result[i++] = cj; result[j--] = ci; } } return new String(result); }
|
总结
利用 双指针法
来遍历字符串,所有元素只需要遍历一次即可得到预期结果,则时间复杂度为 O(n)。
额外变量只有 start
和 end
两个,所以空间复杂度为 O(1)。