【剑指Offer-字符串】面试题5:替换空格

题目描述

请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。

思路1

一种比较容易想到的方法就是从左到右遍历该字符串,当碰到空格的时候就把空格替换为%20,因为从1个字符(' ')替换为了3个字符('%20'),所以要对空格后面的字符进行移动。假设字符串长度为n,对于每个空格字符,需要移动后面的O(n)的字符,因此对于含有O(n)个空格字符的字符串而言,总的时间复杂度为\(O(n^2)\)

思路1对应的代码如下

class Solution {
public:
    // str为输入的字符串,length为总的可用长度
    void replaceSpace(char *str,int length) {
        if(str==nullptr || length==0)
            return;
        
        int strLen = 0;    //字符串长度
        while(str[strLen]!='\0')
            strLen++;
        
        for(int i=0; i<strLen; i++){
            if(str[i]==' '){
                for(int j=strLen; j>i; j--)
                    str[j+2] = str[j];    //注意是加2
                str[i] = '%';
                str[i+1] = '2';
                str[i+2] = '0';
                strLen += 2;
            }
        }
          
    }
};

思路2

思路1的时间复杂度太高了,思路1是从左到右扫描字符串然后移动,这就导致了一些字符被移动多次。可以换一个思路,从右到左扫描字符串。首先分配好替换后字符串的空间,如果原来的字符串为n,共s个空格字符,那么替换后的字符串长度为n+2*s。我们设置两个指针,一个指向替换前的字符串末尾p1,另一个指向替换后的字符串末尾p2。两个指针都从右向左移动,首先对当前p1指向的字符进行判断:若p1指向的字符c1不是空格,那么将c1复制到p2指向的位置,p2向左移动一位;如果p1指向的字符c1是空格,那么将p2以及p2的左两位填充为%20,p2向左移动2位。最后,将p1向左移动一位,重复此过程,直至p1将替换前的字符串从右到左遍历一遍。假设字符串长度为n,因为所有的字符只移动1次,所以时间复杂度为O(n)。

思路2对应的代码如下

class Solution {
public:
    void replaceSpace(char *str,int length) {
        if(str==nullptr || length==0)
            return;
        
        int strLen = 0;
        int bsCnt = 0;    //空格个数
        for(int i=0; str[i]!='\0'; i++){
            strLen++;
            if(str[i]==' ')
                bsCnt++;
        }
        int newStrLen = strLen + 2*bsCnt;
        
        int cur1 = strLen;    //替换前的字符串长度
        int cur2 = newStrLen;    //替换后的字符串长度
        while(cur1>=0 && cur2>cur1){    //条件只写cur1>=0牛客网可以通过
            if(str[cur1]==' '){
                str[cur2--] = '0';
                str[cur2--] = '2';
                str[cur2--] = '%';
            }
            else str[cur2--] = str[cur1];
            cur1--;
        }
          
    }
};

总结

在合并两个字符串(或者数组时),如果从左到右复制每个字符(或数字),则需要重复移动字符(或数字)多次。这种情况下,可以考虑从右向左移动字符,这样能减少移动的次数,从而提高效率。

猜你喜欢

转载自www.cnblogs.com/flix/p/12163471.html