剑指offer 题5—替换空格

题目

请实现一个函数,把字符串中的每个空格替换成“%20”。例如,输入“We are happy.",
则输出"We%20are%20happy."。

首先拿到题目,第一感觉就是一个 ‘空格’ 变成了 ‘%20’ 那字符串长度肯定变长

所以我第一反应是创建新的字符串B,然后从A一个个读取字符,遇到‘空格’就用 ‘%20’ 来替代,只要B空间足够,遍历一遍就成了。

但是,面试再简单也不是考这种题目。
于是这时候面试官可能会讲了:

要求在原来的字符串上进行操作

这时候问题就有点意思了,长度变长绝对会覆盖后面的字符,那么肯定需要移动后面的字符,移就移呗,总比不动好,于是:

  • 时间复杂度O(n2)的解决办法(想拿offter没门)
    思路很简单,当我遇到一个空格时,就将后面的字符全部后移2位,填充%20后,继续遍历,遇到空格就后移,直到最后。
    在这里插入图片描述
    可以看到,“are” 被移动了1次,”happy"移动了2次。要是空格多了,而且又分布在前面岂不是凉凉。

所以要另找出路,就想降低移动次数,正着不行,反着总可以了吧
既然长度要变,不是可以把长度给算出来么,一个萝卜一个坑,一一对应总不会错。

  • 时间复杂度O(n)的解决办法(面试官会心一笑)
    不过我们可以从尾巴开始

1、先遍历一遍字符串,将空格个数计数出来,算出最终字符串总长度
2、利用两个指针P1、P2。一开始P1指向原始字符串末尾,P2只想最终的末尾。
3、P1一格一格向前移动,每移动一次,就将指向的字符(非空)复制到P2(复制完后P2也随之向前移动一格)
4、当P1遇到空格时,P2所在的地方依次填充 0 2 % (即倒着的%20)
5、如果P1与P2相遇了,那么就停止,否则继续进行

来个图示比较清楚
在这里插入图片描述
我们发现所有的字符值移动了1次,这样时间效率提高了,复杂度就变为了O(n)

好了,思路有了,直接敲代码

void ReplaceBlank(char string[],int length)
{
    if(string==nullptr || length<=0)  return;

    //记录原始长度 以及 空格数量
    int originalLength=0;
    int numberOfBlank=0;
    int i=0;
    while(string[i]!='\0')
    {
        ++originalLength;
        if(string[i]=='') ++numberOfBlank;
        ++i;
       } 
    
    //新的长度
    int newLength =  originalLength+numberOfBlank*2;
    if(newLength>length) return;
    
    //"指针" P1 P2
    int indexOfOriginal=originalLength;
    int indexOfNew=newLength;

    while(indexOfOriginal >= 0 && indexOfNew > indexOfOriginal)
    {
        if(string[indexOfOriginal]==' ')  //填充
        {
            string[indexOfNew--]='0';
            string[indexOfNew--]='2';
            string[indexOfNew--]='%';
            }
        else
                 string[indexOfNew--]=string[indexOfOriginal];

        --indexOfOriginal;
        }
}

————————————————————————————————————————————————————
参考书籍:《剑指offer 第二版》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值