题目链接: https://leetcode.cn/problems/ti-huan-kong-ge-lcof/
1. 题目介绍(05. 替换空格)
请实现一个函数,把字符串 s 中的每个空格替换成"%20"。
【测试用例】:
示例1:
输入:s = “We are happy.”
输出:“We%20are%20happy.”
【条件约束】:
0 <= s 的长度 <= 10000
2. 题解
2.1 3倍字符数组扩容 – O(n)
时间复杂度O(n),空间复杂度O(n)
class Solution {
public String replaceSpace(String s) {
// 1. 获取字符串长度
int strLen = s.length();
// 2. 创建三倍字符串长度的字符数组,确保所有值均为空格,也能满足条件
char[] res = new char[strLen * 3];
// 3. 定义一个int变量,用以记录真实数组长度,并作为数组索引
int size = 0;
// 4. 遍历字符串
for (Character c : s.toCharArray()) {
// 5. 当前字符为空格,当前索引3位,将赋值为%20
if (c == ' ') {
res[size++] = '%';
res[size++] = '2';
res[size++] = '0';
} else {
// 6. 不是,则正常赋值
res[size++] = c;
}
}
/**
* tips:
* 此处不能图省事直接使用String.valueOf(),
* 否则因为新数组的长度问题,后面会多出一些空字符
*/
// return String.valueOf(newStr); // We%20are%20happy%20
// 因此更推荐使用下面的方法
String newStr = new String(res, 0, size);
return newStr;
}
}
2.1.1 toString() & String.valueOf()
如果使用程序中返回的是String.valueOf(newStr);
,则会出现下列情况:
而如果此时,使用的是newStr.toString()
,输出的则是新创建的字符串的地址值:
这是由于字符数组使用的toString()
方法是来自Object类的,而数组类中并没有对此方法重写(override),仅仅是重载(overload)为类的静态方法(参见java.util.Arrays)。所以,数组直接使用toString()的结果也是[类型@哈希值]。
那么String.valueOf()
是什么情况呢?
从上图,我们可以看到String类中的valueOf()
方法创建了一个新的String对象,那么再往下看:
看到这里,就一目了然, 他的底层就是我们推荐使用的方法,直接使用String类的带参构造方法创建String对象,这不过由于我们创建的是3倍长度的数组,所以这里的value.length也是3倍的长度。
2.2 StringBuilder – O(n)
时间复杂度O(n),空间复杂度O(n)
class Solution {
public String replaceSpace(String s) {
// 1. 定义一个StringBuilder对象
StringBuilder res = new StringBuilder();
// 2. 循环遍历字符串,并将其添加到StringBuilder对象中
for(Character c : s.toCharArray())
{
// 3. 当前字符如果为空格,添加%20
if(c == ' ') res.append("%20");
// 4. 不是,则正常添加
else res.append(c);
}
// 5. 循环结束,返回字符串
return res.toString();
}
}
【注意】:这里的StringBuilder对象使用的toString()方法是经过了重写的,如下所示:
2.3 replace() – O(n)
使用库函数,轻松搞定!
class Solution {
public String replaceSpace(String s) {
return s.replace(" ","%20");
}
}
2.4 双指针(适用于C)
时间复杂度:O(n),空间复杂度:O(1)
参考代码随想录:剑指 Offer 05. 替换空格:【双指针法】详解
从后向前填充元素,避免了从前先后填充元素要来的 每次添加元素都要将添加元素之后的所有元素向后移动。但除了C/C++,基本上其他语言版本都做不了空间O(1)的复杂度。
class Solution {
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;
}
};
3. 可参考资料
[1] 面试题05. 替换空格 (字符串修改,清晰图解)
[2] 面试题05. 替换空格
[3] What is the time complexity or Big O notation for “str.replace()” built In function in Javascript?