1. 题目来源
链接:LeetCode 替换空格
链接:NowCoder 替换空格
来源:LeetCode——《剑指-Offer》专项
来源:NowCoder——《剑指-Offer》专项
2. 题目说明
请实现一个函数,把字符串 s 中的每个空格替换成"%20"。
示例 1:
输入:s = “We are happy.”
输出:“We%20are%20happy.”
限制:
- 0 <= s 的长度 <= 10000
3. 题目解析
3.1 方法一:string大法好
来自LeetCode 替换空格 string 简单操作直接搞定,不是重点,不解释。
参见代码如下:
// 执行用时 :0 ms, 在所有 C++ 提交中击败了100.00%的用户
// 内存消耗 :8.4 MB, 在所有 C++ 提交中击败了100.00%的用户
class Solution {
public:
string replaceSpace(string s) {
string str;
string tmp = "%20";
for (auto& e : s) {
if (e != ' ')
str.push_back(e);
if (e == ' ')
str += tmp;
}
return str;
}
};
3.2 方法二:从前往后移动替换
朴素思想,从前往后遍历字符串,遇到空格,将空格后的字符串统一后移两位,留出两个空格,依次添加 %
、2
、0
即可。但是频繁的向后搬运空格的操作,势必每次遍历空格后的字符串,假设字符串长度为 n
,对于每个空格字符,需要移动后面
O
(
n
)
O(n)
O(n) 个字符,,因此对于
O
(
n
)
O(n)
O(n) 个空格字符的字符串而言,时间复杂度为
O
(
n
2
)
O(n^2)
O(n2)。
虽说完成了要求,但是时间复杂度很不理想~,在此不列代码,没啥意义。
3.3 方法三:从后往前移动替换
这个思想厉害了:
- 首先遍历字符串统计得到所有的空格数为
cnt
,一个空格代表向后移动 2 位,那么就直接在后面开辟2 * cnt
的空间 - 采用双指针,一个在原字符串尾部的
\0
处,一个在新开辟空间的尾部。 - 依次从后往前进行比遍历
- 遇到空格了,就在尾指针处添加
0
、2
、%
,由于是从后向前遍历,也就逆序添加,尾指针跟着向前走,始终指向空格 - 遇到有效字符了,就将头指针指向字符搬给尾指针所在空格即可,并将尾指针、头指针同时向前 +1
- 当头、尾相遇,此时添加完毕,返回即可
下面这张图很好的阐述了这个思想:
这样操作,遇到空格了,字符串仅需要搬运一次,时间复杂度为
O
(
n
)
O(n)
O(n) ,也是满意的做法了。
class Solution {
public:
void replaceSpace(char *str,int length) {
//遍历一边字符串找出空格的数量
if (str == NULL || length < 0)
return;
int i = 0;
int oldnumber = 0; //记录以前的长度
int replacenumber = 0;//记录空格的数量
while (str[i]!='\0') {
oldnumber++;
if (str[i]==' ') {
replacenumber++;
}
i++;
}
int newlength = oldnumber + replacenumber * 2;//插入后的长度
if(newlength > length)//如果计算后的长度大于总长度就无法插入
return;
int pOldlength = oldnumber; //注意不要减一因为隐藏个‘\0’也要算里
int pNewlength = newlength;
while (pOldlength >= 0 && pNewlength > pOldlength)//放字符
{
if (str[pOldlength] == ' ') //碰到空格就替换
{
str[pNewlength--] = '0';
str[pNewlength--] = '2';
str[pNewlength--] = '%';
}
else //不是空格就把pOldlength指向的字符装入pNewlength指向的位置
{
str[pNewlength--] = str[pOldlength];
}
pOldlength--; //不管是if还是elsr都要把pOldlength前移
}
}
};
3.3 方法四:坐标关系、统计空格数
还是遍历字符串,统计空格数 count
。此时依旧从后向前进行遍历,如果 str[i] != ' '
,那么就将字符直接进行移动 str[i + 2 * count] = str[i];
,如果遇到空格,依旧进行坐标关系填充 %
、2
、0
即可。思想和方法三一致,时间复杂度为
O
(
n
)
O(n)
O(n)。
class Solution {
public:
void replaceSpace(char *str,int length) {
int count = 0;
for (int i = 0; i < length; ++i){
if (str[i] == ' ')
++count;
}
for (int i = length - 1; i >= 0; --i) {
if (str[i] != ' ') {
str[i + 2 * count] = str[i];
}
else {
--count;
str[i + 2 * count] = '%';
str[i + 2 * count + 1] = '2';
str[i + 2 * count + 2] ='0';
}
}
}
};