替换空格

力扣题目链接(opens new window)

请实现一个函数,把字符串 s 中的每个空格替换成"%20"。

示例 1: 输入:s = "We are happy."
输出:"We%20are%20happy."

思路

一个错误思路:

class Solution {
public:
    string replaceSpace(string s) {
        for(int i = 0; i < s.size(); i++){
            if(s[i] == " "){
                s[i] = "%20";
            }
        }
        return s;
    }
};

写python可能可以这么干,但是c++不行

注意审题,我们要插入的 "%20" 是什么东西?这是个字符串

而空格,也就是" ",它是个字符

直接把字符串插到字符的位置,第一,位置不够插不进去,第二,要插也是得一个一个插

这里依然用双指针的方法

替换空格

维护一对双指针,从字符串末尾向头部遍历

两个指针的起点分别为旧字符串和新字符串的末尾,即 i 和 j

当 i 碰到空格时,j从当前位置开始,往前填充待插入的字符串,然后将j跳转到填充结束的位置

如果 i 没碰到空格,正常将 i 位置与 j 位置的字符交换

代码

class Solution {
public:
    string replaceSpace(string s) {
        //先统计空格个数,为扩容做准备
        int count = 0;
        int sOldLen = s.size();//扩容前字符串的长度
        for(int i = 0; i < sOldLen; i++){
            if(s[i] == ' '){
                count++;
            }
        }
        //字符串扩容
        //如示例1,有两个空格,字符串长度为8,如果用待插入的字符串代替空格后,新字符串的长度应该为12(8-2+6)
        s.resize(sOldLen + count*2);//注意不是reserve
        int sNewLen = s.size();
        //维护一对双指针,从字符串末尾开始遍历
        //指针的起点分别为旧字符串长度下的末尾和新字符串长度下的末尾
        for(int i = sOldLen - 1,j = sNewLen - 1; i < j; i--, j--){
            //如果i没有碰到空格,交换i与j的字符
            if(s[i] != ' '){
                s[j] = s[i]; 
            }else{//碰到空格,将j接下来的三位依次替换为插入值
                s[j] = '0';
                s[j - 1] = '2';
                s[j - 2] = '%';
                j-=2;
            }
        }
        return s;
    }
};
易错点
1、字符串扩容

C++中并没有专门的字符串的类型,因此一个字符串实际上就是一个字符数组

是数组就可以扩容

2、reserve和resize的区别

这里容易拿reserve去给数组扩容

首先得区分清楚概念

对于(数组)容器来说,在初始化时,能够描述其"大小"的是两个参数:capacitysize

capacity是容器初始化时的赋值,指的是容器最多能容纳的元素个数(所指容器可以还没创建)

size则是指当前容器中实际的元素个数(所指容器已经创建)

举个例子:

"一个瓶子的容积是550ml(capacity),现在里面装有300ml(size)水"

回到reserve和resize

reserve一般用于为容器预留空间,所谓预留即该容器还没有被创建,等到容器需要创建的时候再按预留空间的大小创建。也就是说reserve可以修改capacity,但不能修改size,因为容器还没创建,没有size属性

再举个例子:

"这次买(创建)的罐装可乐才250ml,不够喝,下次(预留操作,reserve)要买500ml的(修改了下次创建容器时的大小)"

resize则会同时修改capacitysize,此时容器的可用空间会变成新的capacity的大小,

例子:

"我有个小杯子(原容器),里面有300ml水,不够装,我现在马上拿一个500ml的大杯子(扩容,resize)把原来的水装进去,现在够了"

(上述比喻不知道是否贴切,如果resize没有涉及开辟新空间->拷贝原有元素到新空间,那么将比喻中的小杯子换成伸缩杯子会准确一些)