剑指offer之替换空格

替换空格

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

看到这个题目,我们可以想到原来一个空格字符,替换之后变成了’%’,’2’,’0’这三个字符,因此字符串会变长,如果是在原来的字符串上进行替换,就有可能覆盖修改字符串后面的内存。如果是创建新的字符串并在新的字符串上进行替换,那么我们就可以自己分配足够的内存。


本文采用第一种做法: 在原来的字符串上进行替换

第一种思路:
## 从前向后替换 ##

我们可以从头到尾扫描字符串,每当遇见空格时,进行替换,由于我们把一个字符换成了三个字符,所有我们必须把空格之后的所有字符全部向后移两个字节,否则就有两个字节被覆盖了。

让我们来看看这种思路的代码是怎么实现的:

void ReplaceBlank(char *str, int len)//str为字符数组
//len为传入字符数组的总大小  而非字符个数
{
    if(NULL == str || len <= 0) //检验传入的参数是否合格
        return;

    int originlength = 0;//字符串长度
    int numberOfBlank = 0; //空格个数

    char *s = str;
    while(*s != '\0')
    {
        ++originlength;
        if(*s == ' ')
            ++numberOfBlank;
        ++s;
    }
    int newlength = originlength + numberOfBlank * 2;// 替换空格之后字符串的长度

    if(newlength > len)//字符数组不能存入替换后的字符串
        return;

    int i = 0;
    for(; i < originlength; ++i)
    {
        if(str[i] == ' ')
        {
            for(int j = originlength + 2; j - 2 > i; --j)
            {
                str[j] = str[j - 2];
            }
            str[i] = '%';
            str[++i] = '2';
            str[++i] = '0';
            originlength = strlen(str);  //将新的字符串的长度赋值给originlength
        }
    }
}

对于这种从前往后遍历的思路,替换第一个空格,后面的字符需要移动一次,替换第n个空格时,第n个空格后面的字符就移动了n次,总的时间效率是O(n2);


显然 ,上面的方法效率比较低,不能满足我们的要求
那么我们何不换种思路,从后往前替换

第二种思路

从后往前替换

我们可以定义两个指针,p1指向原始字符串末尾,p2指向替换后的字符串末尾,从后向前遍历,把p1指向的字符依次赋给p2,直到p1指向空格,p1前移一位,p2之前插入%20,将p2向前移动3位,依此类推,知道p1和p2指向同一个位置,表示所有空格已经替换完毕。

同样,让我们来看看代码实现 :

void ReplaceBlank(char *str, int len)
{
    if(NULL == str || len <= 0)
        return;

    int originlength = 0;
    int numberOfBlank = 0;

    char *s = str;
    while(*s != '\0')
    {
        ++originlength;
        if(*s == ' ')
            ++numberOfBlank;
        ++s;
    }
    char *p1 = &str[originlength]; //原始字符末尾
    int newlength = originlength + numberOfBlank * 2;
    //替换后的字符串长度,不包括'\0'
    char *p2 = &str[newlength];//替换后的字符末尾

    if(newlength > len)
        return;

    while(p1 != p2)
    //p1 p2指向相同的地址时,表明空格已经全部替换完成
    {
        if(*p1 == ' ')
        {
            --p1;
            *p2-- = '0';
            *p2-- = '2';
            *p2-- = '%';
            continue;
        }
        *p2-- = *p1--;
    }
}

从后往前替换的思路,实现了所有字符只移动一次便完成了替换,因此这个算法的时间复杂度是O(n),比第一个思路要快,从时间角度考虑,我们使用从后往前替换是更优的替换算法。

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页