剑指Offer: 替换空格

剑指Offer: 替换空格

题目描述

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

你可以假定输入字符串的长度最大是1000。
注意输出字符串的长度可能大于1000。

样例
输入:"We are happy."
输出:"We%20are%20happy."

算法1

遍历给定的字符串:

​ 如果遇到空格,则在string类型的答案中添加 “%20”
​ 如果遇到其他字符,则直接将它添加在答案中

时空分析

时间复杂度分析: 原字符串只会被遍历常数次,所以总时间复杂度是 O(n)

C++ 代码
class Solution {
public:
    string replaceSpaces(string &str) {
        string res;
        for (auto ch : str)
        {
            if (ch == ' ')
                res += "%20";
            else
                res +=  ch;
        }
        
        return res;
    }
};

算法2

采用STL的内置函数

时空分析

时间复杂度: replace函数的时间复杂度,由于每次执行该函数,会将一个字符变成三个字符,所以会涉及到数组的整体拷贝,那么每执行一次replace最坏情况下需要 O(n) 的时间,所以总时间复杂度最坏是 O(n2)

C++代码
class Solution {
public:
    string replaceSpaces(string &str) {
        for (string::size_type pos = 0; pos != string::npos; pos += 3)
        {
            pos = str.find(" ", pos);
            if (pos != string::npos)
                str.replace(pos, 1, "%20");
            else
                break;
       }
       return str;
    }
};

算法3 (双指针扫描) O(n)

在部分编程语言中,我们可以动态地将原数组长度扩大,此时我们就可以使用双指针算法,来降低空间的使用:

  1. 首先遍历一遍原数组,求出最终答案的长度length;
  2. 将原数组resize成length大小;
  3. 使用两个指针,指针i指向原字符串的末尾,指针j指向length的位置;
  4. 两个指针分别从后往前遍历,如果str[i] == ’ ‘,则指针j的位置上依次填充’0’, ‘2’, ‘%’,这样倒着看就是"%20";如果str[i] != ’ ',则指针j的位置上填充该字符即可。

由于i之前的字符串,在变换之后,长度一定不小于原字符串,所以遍历过程中一定有i <= j,这样可以保证str[j]不会覆盖还未遍历过的str[i],从而答案是正确的。

时空分析

时间复杂度:原字符串只会被遍历常数次,所以总时间复杂度 O(n)

C++ 代码
class Solution {
public:
	void replaceSpace(char *str,int length) {
        if (!str || length <= 0)
            return;
        int origin = 0;
        int newlength = 0;
        int space = 0;
        char *pstr = str;
        while (*pstr != '\0')
        {
            if (*pstr == ' ')
                space++;
            origin++;
            pstr++;
        }
        
        newlength = origin + 2*space;
        if (newlength > length)
            return;
        
        while(origin >= 0 && newlength > origin)
        {
            if (str[origin] == ' ')
            {
                str[newlength--] = '0';
                str[newlength--] = '2';
                str[newlength--] = '%';   
                --origin;
            }
            else
            {
                str[newlength--] = str[origin--];
            }
        }    
    }  
};
WA原因分析

这道题目之前在牛客上运行时WA了好几回,主要是length长度没有确定好。

错误代码示例

class Solution {
public:
    void replaceSpace(char *str,int length) {
        if (nullptr == str || length < 0)
            return;
        int origin = 0;
        int newlength = 0;
        int space = 0;
        while(str[origin] != '\0')
        {
            if (str[origin] == ' ')
                space++;
            origin++;
        }
         
        newlength = origin + 2*space;
        if (newlength > length)
            return;
        //认为origin长度减1才是字符串的长度
        //但是遍历长度时条件:while(str[origin] != '\0'),这时字符串长度已经没有包含'\0'
        //此时赋值循环的终止条件就出现了错误!!!
        while (origin > 0 && newlength > origin)
        {
            --origin;
            if (str[origin] == ' ')
            {
                str[--newlength] = '0';
                str[--newlength] = '2';
                str[--newlength] = '%';
            }
            else
            {
                str[--newlength] = str[origin];
            }
        }  
    }
};
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Erice_s

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值