Update 5. 替换空格.md

更新题目说明,补充双指针从后往前替换空格的推演示例与 Java 实现代码,并补充替换前后长度不变场景的说明。
This commit is contained in:
CyC2018
2026-10-30 20:18:05 +08:00
parent e01c276f24
commit cb6b28c11b
+48 -3
View File
@@ -6,7 +6,7 @@
## 题目描述
将一个字符串中的空格替换成 "%20"。(在 LeetCode 上对应原题为 LCR 122. 路径加密,题意要求将 '.' 替换为空格)
将一个字符串中的每个空格替换成 "%20"。
```text
Input:
@@ -16,10 +16,55 @@ Output:
"A%20B"
```
力扣上对应的 LCR 122“路径加密”改成了把 '.' 替换为空格,替换前后长度不变,代码见[替换前后长度不变的情况](#替换前后长度不变的情况)。
## 解题思路
① 遍历字符串,统计需要替换字符的个数,据此计算出替换后所需的新长度。
② 双指针或 StringBuilder 处理:遍历原字符串,遇到目标字符则追加替换后的内容,其余字符原样复制。
Java 的 String 不可变,最直接的做法是用 StringBuilder 逐个字符复制,遇到空格追加 "%20",时间和空间复杂度都是 O(N)。
原题考查的是在原数组上替换,假设数组末尾有足够的空余位置。如果从前往后替换,每遇到一个空格,它后面的所有字符都要后移 2 位,最坏 O(N<sup>2</sup>)。从后往前填可以让每个字符只移动一次:
- 先统计空格个数,新长度 = 原长度 + 2 × 空格数;
- P1 指向原字符串的末尾,P2 指向新长度的末尾,P1 从后往前扫描:普通字符复制到 P2,空格则在 P2 处从后往前依次写入 '0'、'2'、'%';
- P1 与 P2 相遇时,前面已经没有空格,结束。
以 "A B C" 为例(_ 表示空格),原长度 5,新长度 9:
```text
下标 0 1 2 3 4 5 6 7 8
初始 A _ B _ C P1 = 4,P2 = 8
复制 C A _ B _ C C P1 = 3,P2 = 7
空格写 %20 A _ B _ C % 2 0 C P1 = 2,P2 = 4
复制 B A _ B _ B % 2 0 C P1 = 1,P2 = 3
空格写 %20 A % 2 0 B % 2 0 C P1 = 0,P2 = 0,相遇
```
```java
public String replaceSpace(String s) {
int spaces = 0;
for (int i = 0; i < s.length(); i++)
if (s.charAt(i) == ' ')
spaces++;
// 模拟末尾留有足够空间的字符数组
char[] chars = Arrays.copyOf(s.toCharArray(), s.length() + 2 * spaces);
int p1 = s.length() - 1, p2 = chars.length - 1;
while (p1 >= 0 && p1 < p2) {
char c = chars[p1--];
if (c == ' ') {
chars[p2--] = '0';
chars[p2--] = '2';
chars[p2--] = '%';
} else {
chars[p2--] = c;
}
}
return new String(chars);
}
```
### 替换前后长度不变的情况
LCR 122 把 '.' 换成空格,一个字符换一个字符,不涉及移动,逐个复制即可。
```java
public String pathEncryption(String path) {