經典字符串題:將字符串中每個空格替換為 %20。本文講解兩種 O(n) 解法——陣列從後向前原地替換(面試首選)與 StringBuffer 索引查找(工程實用),附完整 Java 代碼、邊界測試與複雜度分析。
輸入:"We are happy."
輸出:"We%20are%20happy."
輸入:" We are happy. "
輸出:"%20We%20are%20happy.%20"
%20 長度 +2,需擴容。String 不可變,需轉 char[] 或用 StringBuffer 操作。spaceCount,計算新長度 newLen = oldLen + 2 * spaceCount。char[] newArr = new char[newLen]。i = oldLen - 1 (舊末尾)、j = newLen - 1 (新末尾)。old[i] != ' ' → newArr[j--] = old[i--]old[i] == ' ' → newArr[j]='0'; newArr[j-1]='2'; newArr[j-2]='%'; j-=3; i--new String(newArr)。public static String replaceSpace(char[] str) {
if (str == null) return null;
int oldLen = str.length;
int spaceCount = 0;
for (char c : str) if (c == ' ') spaceCount++;
int newLen = oldLen + 2 * spaceCount;
char[] newArr = new char[newLen];
int i = oldLen - 1, j = newLen - 1;
while (i >= 0) {
if (str[i] == ' ') {
newArr[j--] = '0';
newArr[j--] = '2';
newArr[j--] = '%';
} else {
newArr[j--] = str[i];
}
i--;
}
return new String(newArr);
}
char[])StringBuffer.indexOf(" ", fromIndex) 定位下一個空格。subSequence(from, index) 取非空格段落,append 到結果緩衝區,再 append("%20")。indexOf 返回 -1,最後追加剩餘尾部。public static String replaceSpace(StringBuffer sb) {
if (sb == null) return null;
StringBuffer result = new StringBuffer();
int from = 0, index = 0;
while ((index = sb.indexOf(" ", from)) >= 0) {
result.append(sb.subSequence(from, index)).append("%20");
from = index + 1;
}
result.append(sb.substring(from)); // 剩餘尾部
return result.toString();
}
indexOf 內部優化,整體線性| 輸入 | 預期輸出 | 說明 |
|---|---|---|
| "We are happy." | "We%20are%20happy." | 基本情況 |
| " We are happy. " | "%20We%20are%20happy.%20" | 首尾空格 |
| "Wearehappy." | "Wearehappy." | 無空格 |
| "" | "" | 空字符串 |
| " " | "%20" | 單空格 |
| null | null | 空引用保護 |
C/C++ 常見變體:假設 char str[100] 末尾有足夠空間,無需額外陣列 真正 O(1) 空間:
// C 風格偽碼
int oldLen = strlen(str);
int spaceCount = count_spaces(str);
int newLen = oldLen + 2 * spaceCount;
str[newLen] = '\0';
for (int i = oldLen - 1, j = newLen - 1; i >= 0; i--) {
if (str[i] == ' ') {
str[j--] = '0'; str[j--] = '2'; str[j--] = '%';
} else {
str[j--] = str[i];
}
}
Java char[] 長度不可變,無法直接應用,但理解此思維有助於解決「合併兩個有序陣列」「移除元素」等原地修改題。
替換空格考察「從後向前掃描避免重複移動」的陣列技巧與 StringBuffer 實戰能力。面試建議:首寫陣列雙指針版展示演算法功力,再補 StringBuffer 版說明工程落地;邊界情況(null、空串、首尾空格)主動測試,體現嚴謹風格。