編寫函數,接收一個字符串,僅反轉其中的元音字母 (a, e, i, o, u, A, E, I, O, U),其他字符位置不變。
示例 1:"hello" → "holle" (e, o 互換)
示例 2:"leetcode" → "leotcede" (e, o, e, e → e, e, o, e)
字符串不可變,轉 char[] 操作。左右雙指針向中間掃描,遇到元音則交換,非元音則移動指針。
public String reverseVowels(String s) {
if (s == null || s.length() <= 1) return s;
// 元音查找集:O(1) 判斷
Set vowels = new HashSet<>(Arrays.asList('a','e','i','o','u','A','E','I','O','U'));
// 或用 boolean[128] 數組更快 (ASCII)
// boolean[] isVowel = new boolean[128];
// for (char c : "aeiouAEIOU".toCharArray()) isVowel[c] = true;
char[] chars = s.toCharArray();
int left = 0, right = chars.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);
}
public String reverseVowels(String s) {
if (s == null || s.length() <= 1) return s;
// ASCII 範圍內 boolean 數組查找最快,無哈希開銷
boolean[] isVowel = new boolean[128];
for (char c : "aeiouAEIOU".toCharArray()) isVowel[c] = true;
char[] chars = s.toCharArray();
int left = 0, right = chars.length - 1;
while (left < right) {
while (left < right && !isVowel[chars[left]]) left++;
while (left < right && !isVowel[chars[right]]) right--;
if (left < right) {
char temp = chars[left];
chars[left] = chars[right];
chars[right] = temp;
left++;
right--;
}
}
return new String(chars);
}
char[] 複製 (Java 字符串不可變) + O(1) 輔助空間| 技術點 | 說明 |
|---|---|
| 雙指針 | 左右夾適,原地交換,單次掃描完成 |
| 元音判斷 | Set/boolean[] 實現 O(1) 查找,避免字符串 indexOf O(k) |
| 邊界條件 | 空串、單字符、無元音、全元音、左右指針相遇 |
| 字符串不可變 | 必須 toCharArray() 操作,最後 new String() 構建結果 |
| 大小寫敏感 | 題目包含大小寫元音,集合/數組需同時包含 |
boolean[] 不適用,改用 HashSet<Character> 或 Character.toLowerCase 統一判斷「雙指針左右掃描,boolean[128] 數組 O(1) 判斷元音,遇到則交換並移動指針。時間 O(n),空間 O(n) (char[] 複製)。注意字符串不可變需轉數組,大小寫全覆蓋,邊界條件 left