题目描述
请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32M,其他语言64M
热度指数:1309646
分析思路
本人在刚开始学习c编程时就遇到过类似的题目,当时,没有不考虑额外的空间开销,直接的思路就是:
- 开辟一个新的字符串数组,然后对原字符串数组从头到尾进行遍历;
- 字符如果不是空格就复制到新字符串中,如果是空格就不复制,并且在新字符串中插入%20;
- 循环进行,直至遍历完原字符串;
上述思路,这里不再具体说明。我们应该探索一个更加高效率的字符串替换算法。
用“%20”来替换字符串中的空格,字符变了,长度变了。如果不开辟新的字符串,无非涉及到两个关键点:移动和替换。而且,为保证字符串替换不出错,移动操作一定在替换操作之前。
刚开始,我考虑问题的时候,我会想:从前往后遍历字符串,遇到空格,就把空格后面的字符往后移,然后在空格处替换。这样虽然能解决问题,但是每次遇到空格都得移动字符串,使得操作变得繁琐,影响效率。
所以,我会想,是否能够一次性把所有的移位操作完成到位?要知道,这里每次的替换规则是固定的,最终得到的字符串也是肯定的,那么这个问题的答案当然就是肯定的了。
解题思路
首先,对替换前后进行对比分析:
第一步:确定移位操作,各字符移动的位数。
- 每次替换:“%20”->" "(三个字符替换一个),字符串增长两个单位;换而言之,一个空格,字符串增长两单位;
- 欲确定最终字符串长度,就需要记录字符串中空格总数;
- 欲确定每个字符向后移动的位数,就需要记录每个字符前的空格数;
第二步:解决上面两个关键性问题
- “记录字符串中空格总数”:遍历整个字符串,用变量count++的方式记录空格数;
- “记录每个字符前的空格数”:既然字符串中总的空格数以及确定,那么最后一个空格后面的字符移动的位数就应该是2 x count,倒数第二个空格和最后一个空格间的字符移动的位数就是2 x(count-1)…以此类推,直至count=0;
- 基于上述规则,确定了我们在进行替换时,对字符串的遍历,应该从后往前进行;
- 字符串移动完毕,替换的空间已经腾出,接着进行简单的替换操作即可;
算法的详细过程参见代码部分;
代码
class Solution {
public:
void replaceSpace(char *str,int length) {
int count=0;
//首先,从前往后遍历字符串,用count记录字符串中的空格数
for(int i=0;i<length;i++){
if(str[i]==' ')
count++;
}
//从后往前反向遍历
//移位每个非空格字符,给空格的替换腾出空间,移动的位数为2*count
for(int i=length-1;i>=0;i--){
if(str[i]!=' '){
str[i+2*count]=str[i];
}
else{
//遇到空格直接开始替换,注意这里逻辑顺序,参考前文图示,弄清为什么要先count--
count--;
str[i+2*count]='%';
str[i+2*count+1]='2';
str[i+2*count+2]='0';
}
}
}
};