咸鱼回响

望之天回,即之云昏

0%

【剑指-offer】05.替换空格

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/ti-huan-kong-ge-lcof

题目描述

请实现一个函数,把字符串 s 中的每个空格替换成”%20”。

示例 1:

输入:s = “We are happy.”
输出:”We%20are%20happy.”

限制:

0 <= s 的长度 <= 10000

我的解题

思路

有两种方法:

  1. 调用replace库函数直接替换
  2. 遍历字符串,用if判断字符是否是空格,如果是则替换

结果

我这里使用方法2

1
2
3
4
5
6
7
8
9
10
11
12
13
class Solution {
public String replaceSpace(String s) {
StringBuilder sb = new StringBuilder();
for (char c : s.toCharArray()) {
if (c == ' ') {
sb.append("%20");
} else {
sb.append(c);
}
}
return sb.toString();
}
}

最优解

思路

如果想把这道题目做到极致,就不要只用额外的辅助空间了!
当然这只是针对C++的情况下,因为在C++中,字符数组是可以在原有的基础上扩充的。

首先扩充数组到每个空格替换成”%20”之后的大小。然后从后向前替换空格,也就是双指针法。

为什么不从前往后扩充呢?如果从前往后扩充的话时间复杂度就是O(n^2)了。因为每次添加元素都要将添加元素之后的所有元素向后移动。

其实很多数组填充类的问题,都可以先预先给数组扩容带填充后的大小,然后在从后向前进行操作。这么做有两个好处:

  1. 不用申请新数组。
  2. 从后向前填充元素,避免了从前先后填充元素要来的 每次添加元素都要将添加元素之后的所有元素向后移动。

结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public:
string replaceSpace(string s) {
int count = 0; // 统计空格的个数
int sOldSize = s.size();
for (int i = 0; i < s.size(); i++) {
if (s[i] == ' ') {
count++;
}
}
// 扩充字符串s的大小,也就是每个空格替换成"%20"之后的大小
s.resize(s.size() + count * 2);
int sNewSize = s.size();
// 从后先前将空格替换为"%20"
for (int i = sNewSize - 1, j = sOldSize - 1; j < i; i--, j--) {
if (s[j] != ' ') {
s[i] = s[j];
} else {
s[i] = '0';
s[i - 1] = '2';
s[i - 2] = '%';
i -= 2;
}
}
return s;
}
};