描述:

这是一道简单的字符串操作的题目,可以锻炼代码能力。

  • 题目难度:一星
  • 考察点:字符串

方法: 逆向遍历

  1. 分析:由于函数返回为void,说明此题不能另外开辟数组,需要in-place操作。我们知道字符串的遍历无非是从左到右和从右到左两种。
    1)如果从左到右,会发现如果遇到空格,会将原来的字符覆盖。于是,此方法不行。
    2)那么就考虑从右向左,遇到空格,就填充“20%“,否则将原字符移动应该呆的位置。
  2. 具体过程如图所示:
  • length为原字符串最后一个字符的位置,new_lngth为结果字符串的最后一个位置
    图片说明
  • 如果str[length]不等于空格,就复制,然后指针分别左移一位。
    图片说明
  • 如果str[length]等于空格,就填充“20%”
    图片说明
  • 一直进行上述步骤,直到字符串遍历完毕
    图片说明
  1. 代码:
    class Solution {
    public:
     void replaceSpace(char *str,int length) {
         if (str == nullptr || length <= 0) return; // 养成良好习惯,判空操作
         int cnt = 0;  // 空格的个数
         for (int i=0; i != length; ++i) {
             if (str[i] == ' ') ++cnt;
         }
         if (!cnt) return; // 没有空格,直接返回
         int new_length = length+cnt*2;
         for (int i=length; i >= 0; --i) {
             if (str[i] == ' ') {
                 str[new_length--] = '0';
                 str[new_length--] = '2';
                 str[new_length--] = '%';
             }
             else {
                 str[new_length--] = str[i];
             }
         }
     }
    };
  2. 复杂度分析
    时间复杂度:O(length) 只遍历了一遍字符串
    空间复杂度:O(1) 没有开辟空间

拓展话题

c库函数中内存拷贝memmove()函数与此题有共同点,函数功能就是:将起始地址src且长度为count的内存拷贝到起始地址dst处,并返回dst,返回是为了实现链式表达式。源代码如下:
函数原型为:void* __cdecl memmove(void *dst, const void *src, size_t count;

void* __cdecl memmove (void *dst, const void *src, size_t count) 
{
    void *ret = dst;
    if (dst <= src || (char *)dst >= ((char *)src + count)) 
    {
        // 若dst 和 src区域没有重叠,则从起始处开始逐一拷贝
        while (count--) 
        {
            *(char *)dst = *(char *)src;
            dst = (char *)dst + 1;
            src = (char *)src + 1;
        }
    }
    else 
    {
        // 区域重叠,从尾部开始拷贝
        dst = (char *)dst + count - 1;
        src = (char *)src + count - 1;
        while (count--) 
        {
            *(char *)dst = *(char *)src;
            dst = (char *)dst - 1;
            src = (char *)src - 1;
        }
    }
    return (ret);
}

当src 和 dst 存在区域重叠时, 就会从右向左拷贝。这一点与此题有异曲同工之妙!