[剑指 Offer 05. 替换空格]

103 阅读2分钟

[剑指 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循环的工作,大大优化了时间复杂度,并且讨论了适合双指针开始的位置。