[剑指 Offer 05. 替换空格]
「这是我参与2022首次更文挑战的第12天,活动详情查看:2022首次更文挑战」。
题目描述
请实现一个函数,把字符串 s 中的每个空格替换成"%20"。
示例
示例1 :
输入: s = "We are happy."
输出: "We%20are%20happy."
限制:
0 <= s 的长度 <= 10000
思路
这道题其实实现起来并不困难,有一个思路非常明显,那就是直接遍历数组,当找到空格后,将该元素后的其他元素直接往后搬3位,再将空出来的位置改为“%20”,十分好理解,但是细想,上面的那种算法耗时将主要在搬运元素上面。代码实现上,就是两层for循环嵌套,一层找并改目标元素,一层搬运元素。结合我们在昨天双指针所说的,双指针就是通过前后两个指针不短的移动,在一个for循环下完成两个for循环的工作,并且字符串也是线性的数据结构。我们可以往双指针这个方向来想。具体到这道题和两层for循环,我们可以想到一个找并改元素,一个来搬元素,和昨天那道题有相识的地方。
代码实现
class Solution {
public:
string replaceSpace(string s) {
int count=0;
int Oldsize=s.size();
for(int i=0;i<Oldsize;i++){ //计算空格的数量
if(s[i]==' ')
count++;
}
s.resize(Oldsize+2*count); //调用字符串的扩容函数
int Newsize=s.size();
for(int i=Oldsize-1,j=Newsize-1;i<j;i--,j--){ //i为慢指针,指向原始数据尾部
if(s[i]!=' ') //j为快指针,指向扩容后数组尾部
s[j]=s[i]; //当i,j相遇时,i,j前的字符串一致,没有空格 else{
s[j]='0';
s[j-1]='2';
s[j-2]='%';
j-=2;
}
}
return s;
}
};
在实现上,这道题的最大区别就是从字符串的末尾开始。这么做的原因是实际上,我们实际上是在对字符串进行一个扩容,不能在原地进行修改,在原地修改会导致原始数据的丢失。而昨天的那道是在缩小,原地修改时,覆盖的数据已经是处理过的数据,可以放心覆盖。既然从尾部开始,那么需要我们确定扩容后字符串的大小,所以需要计算空格的数量,对数组进行扩容。之后使用与昨天类似的快慢双指针来完成任务。
总结
上述内容使用双指针的算法思想,使用快慢指针,通过前后两个指针不短的移动,在一个for循环下完成两个for循环的工作,大大优化了时间复杂度,并且讨论了适合双指针开始的位置。