剑指Offer4 替换空格

原题: 

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

分析:

看到这个问题第一感觉很简单,就是简单的字符串替换问题,很简单的方法就能实现。但是当细心一想,就会发现其时间效率是很重要的一个要解决方面。
最原始的想法是从头到尾遍历其整个数组,遇到空格就转化,当把一个空格转化成三个字符就相当于后面的字符需要向后移动,这时就会想到,每遇到一个空格,就需要往后移动后面的数组中的内容,这样他的时间复杂度就成了O(n2)。这肯定是不行的。
那么还有其他思路吗?
1,如果可以使用辅助内存,那这个题目也很简单,new一个新的数组,来存放转化之后的字符串,做两个指针p1,p2,p1指向原始字符串的首地址,p2指向新的。遇到空格p2往后移动三个,并将其相应的转化成要转化的字符。
2,如果不能使用辅助内存,就只能允许在原始的数组上向后扩充,并且数组足够大。那么怎么办?
其实遇到这种字符串转换的,就要形成思维定式了,试一下从后往前遍历数组。先遍历一边数组,计算出数组的长度和空格数目,那么最后数组的长度就newLength = oldLength + numBlank*2(一个字符被替换成了三个字符)。这样再设置两个指针,一个指向当前数组的最后一个字符,另一个指向最终长度的最后一个指针,剩下的方法就同1了。

代码

#include <iostream>


using namespace std;


void ReplaceBlank(char *str,int length)
{
    if(str == NULL || length <= 0)
        return ;
    int numBlank=0,lengthOfStr=0;
    int i=0;
    while(str[i] != '\0')
    {
        ++lengthOfStr;
        if(str[i] == ' ')
            ++numBlank;
        ++i;
    }
    int lengthOfEnd = lengthOfStr + numBlank * 2 ;
     int p1 = lengthOfStr;
     int p2 = lengthOfEnd;


    if(lengthOfEnd > length)
        ///这个判断表示如果替换完之后之前的数组不够长
        return ;


    str[lengthOfEnd+1] = '\0';
    while(p1>=0 && p2 >=0)
    {
        if(str[p1] == ' ')
        {
            str[p2--] = '0';
            str[p2--] = '2';
            str[p2--] = '%';
        }
        else
        {
            str[p2--] = str[p1];
        }
        p1--;
    }


}


int main()
{
    char str[20] = "   ";
    ReplaceBlank(str,20);
    cout<<str<<endl;
    return 0;
}

注意

1,空指针的异常判断
2,转化之后可能超出原数组的异常


相关题目:

有两个排序数组,A1,A2,内存在A1的末尾有足够多的空余空间容纳A2。请实现一个函数,把A2中的所有数字插入到A1中并且所有的数字是排序的

解决思路:

从尾到头比较A1和A2中的数字,并把较大的数字复制到A1的合适位置。

代码

#include <iostream>


using namespace std;


void Merger(int *a,int *b,int lenA,int lenB)
{
    if(a == NULL || b == NULL || lenA <= 0 || lenB <= 0)
        return ;
    int length = lenA + lenB+1;
    while(lenA>=0 && lenB>=0 && length>=lenA)
    {
        if(a[lenA]>b[lenB])
            a[length--] = a[lenA--];


        else if(a[lenA] < b[lenB])
            a[length--] = b[lenB--];


        else
        {
            a[length--] = a[lenA--];
            a[length--] = b[lenB--];
        }
    }
    while(lenA>=0 && length>=0)
        a[length--] = a[lenA--];
    while(lenB>=0 && length>=0)
        a[length--] = b[lenB--];
}


int main()
{
    int a[10] = {1,2,4};
    int b[4] = {3,5,6};
    Merger(a,b,2,2);
    for(int i=0;i<10;i++)
        cout << a[i] << "  ";
    cout<<endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值