字符串反轉是面試高頻考點,也是基礎算法練翐。Java 中字符串不可變,反轉本質是創建新字符串。本文總結 7 種常見實現,從遞歸到位運算,並分析時間空間複雜度與適用場景。
public static String reverse1(String s) {
int len = s.length();
if (len <= 1) return s;
String left = s.substring(0, len / 2);
String right = s.substring(len / 2);
return reverse1(right) + reverse1(left);
}
特點:代碼優雅,但遞歸深度 O(log n),大量字符串拼接導致 O(n log n) 時間複雜度,不推薦生產使用。
public static String reverse2(String s) {
String rev = "";
for (int i = 0; i < s.length(); i++) {
rev = s.charAt(i) + rev;
}
return rev;
}
特點:每次拼接創建新字符串,時間複雜度 O(n²),極其低效。
public static String reverse3(String s) {
char[] arr = s.toCharArray();
String rev = "";
for (int i = arr.length - 1; i >= 0; i--) {
rev += arr[i];
}
return rev;
}
特點:同樣存在字符串拼接性能問題,JDK 9+ 會優化為 StringBuilder,但仍不如顯式構建器。
public static String reverse4(String s) {
return new StringBuilder(s).reverse().toString();
}
特點:標準庫實現,高度優化,線程安全。單線程環境首選 StringBuilder,多線程用 StringBuffer。
public static String reverse5(String s) {
char[] arr = s.toCharArray();
int n = arr.length - 1;
int half = n / 2;
for (int i = 0; i <= half; i++) {
char tmp = arr[i];
arr[i] = arr[n - i];
arr[n - i] = tmp;
}
return new String(arr);
}
特點:原地交換,空間 O(n),時間 O(n),手寫算法面試首選。
public static String reverse6(String s) {
char[] arr = s.toCharArray();
int l = 0, r = s.length() - 1;
while (l < r) {
arr[l] = (char) (arr[l] ^ arr[r]);
arr[r] = (char) (arr[l] ^ arr[r]);
arr[l] = (char) (arr[r] ^ arr[l]);
l++; r--;
}
return new String(arr);
}
特點:位運算技巧,避免臨時變量,但現代 JVM 優化下無性能優勢,可讀性差,不推薦。
public static String reverse7(String s) {
char[] arr = s.toCharArray();
Stack stack = new Stack<>();
for (char c : arr) stack.push(c);
StringBuilder sb = new StringBuilder();
while (!stack.isEmpty()) sb.append(stack.pop());
return sb.toString();
}
特點:利用棧特性,空間 O(n),時間 O(n),適合教學演示棧應用。
| 方法 | 時間複雜度 | 空間複雜度 | 推薦場景 |
|---|---|---|---|
| StringBuilder.reverse() | O(n) | O(n) | 生產環境首選,代碼簡潔、性能優異 |
| 雙指針數組交換 | O(n) | O(n) | 面試手寫、嵌入式環境、需自定義邏輯時 |
| 棧結構 | O(n) | O(n) | 數據結構教學、需中間過程可視化 |
| 遞歸/拼接法 | O(n²)或更高 | O(n²) | 避免使用,僅作算法思維練習 |
上述方法基于 char (UTF-16 代碼單元),對於 Emoji 等補充字符(佔 2 個 char)會反轉錯誤。正確處理需使用 codePoint API:
public static String reverseUnicodeSafe(String s) {
int[] codePoints = s.codePoints().toArray();
for (int i = 0, j = codePoints.length - 1; i < j; i++, j--) {
int tmp = codePoints[i];
codePoints[i] = codePoints[j];
codePoints[j] = tmp;
}
return new String(codePoints, 0, codePoints.length);
}
日常開發**直接使用 new StringBuilder(s).reverse().toString()**;面試手寫掌握**雙指針數組交換**;理解各方法優劣,根據場景選擇。切記:字符串不可變,反轉本質都是創建新對象。