剑指offer-2:替换空格
目录
1题目描述
请实现一个函数,将一个字符串中的空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。
2问题解析
该问题的考察不是string类里面的find()、replace()函数
用3个字符替换一个字符,注意字符覆盖的问题
思路是:从前往后遍历,还是从后往前遍历
- 从前往后替换,后面的字符要不断往后移动,要移动多次,所以效率低下
- 从后往前,先计算需要多少空间,然后从后往前移动,则每个字符只移动一次,这样效率更高一点。
从前向后遍历寻找到空格,并移动后面元素再进行替换的想法很简单,但是时间复杂度高,每一个空格后面的元素都要向后移动,会涉及后面的元素存在多次移动的问题,时间复杂度为O(n);
但是如果换一种思路,先规定好字符数组可允许访问的长度。统计原字符串中所拥有的空格数。
使用两个指针P1和P2,P1指向原字符串的末尾,P2指向替换后的字符串的末尾。
从后向前复制字符串,遇到空格,P2从后向前添加符号,移动3个单位,P1则向前移动1个单位。
当P1和P2位置相遇时则说明所有空格已经替换。
- 注意,字符串尾部 “\0”的问题
3答案和完整代码
答案:
class Solution {
public:
// length替换后的字符总长度上限
void replaceSpace(char *str,int length) {
if(str==NULL || length<=0)
return;
int originalLength = 0; //记录以前字符串长度
int numberOfBlank = 0; //记录空格数量
int i = 0;
//遍历一遍字符串,找出空格数量,原字符串长度
while(str[i]!='\0'){
++originalLength;
if(str[i]==' ')
++numberOfBlank;
++i;
}
int newLength = originalLength + 2 * numberOfBlank;
if(newLength>length)
return;
int indexOfOriginal = originalLength;
int indexOfNew = newLength;
while(indexOfOriginal>=0 && indexOfNew>indexOfOriginal){
//遇到空格就替换
if(str[indexOfOriginal]==' '){
str[indexOfNew--]= '0';
str[indexOfNew--]= '2';
str[indexOfNew--]= '%';
}
else
{
str[indexOfNew--] = str[indexOfOriginal];
}
--indexOfOriginal; //前移 indexOfOriginal
}
return;
}
};
- 完整代码:
- 实际上str[0]和str[1]并没有被替换,因为indexOfNew与indexOfOriginal同时为1,没有进入到循环中,str[0]与str[1]保留了原来的值
#include <iostream>
using namespace std;
class Solution {
public:
// length替换后的字符总长度上限
void replaceSpace(char *str,int length) {
if(str==NULL || length<=0)
return;
int originalLength = 0; //记录以前字符串长度
int numberOfBlank = 0; //记录空格数量
int i = 0;
//遍历一遍字符串,找出空格数量,原字符串长度
while(str[i]!='\0'){
++originalLength;
if(str[i]==' ')
++numberOfBlank;
++i;
}
int newLength = originalLength + 2 * numberOfBlank; //替换字符串后,新字符串的长度
if(newLength>length) //新字符串长度如果大于上限,则无法插入
return;
int indexOfOriginal = originalLength; // 字符串的索引【不用减一,因为隐藏的 '\0’也要计算在内】
int indexOfNew = newLength;
cout<<"原字符串末尾索引:"<<indexOfOriginal<<endl;
cout<<"新字符串末尾索引:"<<indexOfNew<<endl;
while(indexOfOriginal>=0 && indexOfNew>indexOfOriginal){
//遇到空格就替换
if(str[indexOfOriginal]==' '){
cout<<"遇到空格时的新字符串索引"<<indexOfNew<<endl;
str[indexOfNew--]= '0';
str[indexOfNew--]= '2';
str[indexOfNew--]= '%';
cout<<"遇到空格时,替换后的新字符串索引"<<indexOfNew<<endl;
}
//不是空格,就把indexOfOriginal指向的字符放入indexOfNew指向的位置
else
{
cout<<"没遇到空格时的新字符串索引"<<indexOfNew<<endl;
str[indexOfNew--] = str[indexOfOriginal];
cout<<"没遇到空格时,放置后的新字符串索引"<<indexOfNew<<endl;
}
cout<<"原字符串索引"<<indexOfOriginal<<endl;
--indexOfOriginal; //前移 indexOfOriginal
cout<<"--原字符串索引"<<indexOfOriginal<<endl;
cout<<endl;
}
return;
}
};
int main()
{
Solution solution;
char strings[]="We are happy";
solution.replaceSpace(strings, 30);
cout<<strings<<endl;
}
原字符串末尾索引:12
新字符串末尾索引:16
没遇到空格时的新字符串索引16
没遇到空格时,放置后的新字符串索引15
原字符串索引12
–原字符串索引11
没遇到空格时的新字符串索引15
没遇到空格时,放置后的新字符串索引14
原字符串索引11
–原字符串索引10
没遇到空格时的新字符串索引14
没遇到空格时,放置后的新字符串索引13
原字符串索引10
–原字符串索引9
没遇到空格时的新字符串索引13
没遇到空格时,放置后的新字符串索引12
原字符串索引9
–原字符串索引8
没遇到空格时的新字符串索引12
没遇到空格时,放置后的新字符串索引11
原字符串索引8
–原字符串索引7
没遇到空格时的新字符串索引11
没遇到空格时,放置后的新字符串索引10
原字符串索引7
–原字符串索引6
遇到空格时的新字符串索引10
遇到空格时,替换后的新字符串索引7
原字符串索引6
–原字符串索引5
没遇到空格时的新字符串索引7
没遇到空格时,放置后的新字符串索引6
原字符串索引5
–原字符串索引4
没遇到空格时的新字符串索引6
没遇到空格时,放置后的新字符串索引5
原字符串索引4
–原字符串索引3
没遇到空格时的新字符串索引5
没遇到空格时,放置后的新字符串索引4
原字符串索引3
–原字符串索引2
遇到空格时的新字符串索引4
遇到空格时,替换后的新字符串索引1
原字符串索引2
–原字符串索引1
We%20are%20happy
- 简洁版
#include <iostream>
using namespace std;
class Solution {
public:
void replaceSpace(char *str,int length) {
if(str==NULL || length<=0) return;
int originalLength = 0;
int numberOfBlank = 0;
int i = 0;
while(str[i]!='\0'){
++originalLength;
if(str[i]==' ')
++numberOfBlank;
++i;}
int newLength = originalLength + 2 * numberOfBlank;
if(newLength>length) return;
int indexOfOriginal = originalLength;
int indexOfNew = newLength;
while(indexOfOriginal>=0 && indexOfNew>indexOfOriginal){
if(str[indexOfOriginal]==' '){
str[indexOfNew--]= '0';
str[indexOfNew--]= '2';
str[indexOfNew--]= '%';}
else{
str[indexOfNew--] = str[indexOfOriginal];}
--indexOfOriginal; //前移 indexOfOriginal
}
return;
}
};
int main()
{
Solution solution;
char strings[]="We are happy";
solution.replaceSpace(strings, 30);
cout<<strings<<endl;
}