剑指offer-04:字符串替换空格

题目:实现一个函数,把字符串中的每个空格替换为”%20”。

题目背景:网络编程中URL参数中的特殊字符,如空格,#等需要转换为服务器可以识别的字符,转换规则是在%后面加上其ASCII码的两位十六进制表示。空格的ASCII码是32,十六进制为0x20,空格被替换为%20。

首先:新字符串还是原字符串?

若是新字符串,则分配可容纳空间,然后扫描原字符串,遇见空格特殊处理,其余字符原样复制。这没啥难度。

若是原字符串上,考虑2个问题:

  • 空格从占1位扩展到3位,增加2位,不能覆盖其后的原值;
  • 因为扩充,原字符串后面要有足够大的空间供替换

解决思路:每个空格会增加2位后移,则根据每个非空格字符前的空格数目,可以计算出该字符的最终位置。为了不覆盖后面内容,我们从后往前扫描,先移动后面的覆盖新内存,再往前,移动覆盖后面的内存。 O(n)

笨办法:从前往后扫描,遇到空格,则把该空格后面的字符串整体后移。这样导致越往后的字符串被移动的次数越多,不必要的开销。 O(n2)

// offer-04-string-replace.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>

using namespace std;

char * replace(char str[], int length) 
{
    // 字符串NULL指针,空串判断
    if (str == nullptr || length <= 0)
        return str;

    // 统计字符个数和空格个数
    int originLength = 0;
    int numberOfSpace = 0;
    int i = 0;
    while (str[i] != '\0')
    {
        ++originLength;
        if (str[i] == ' ')
            ++numberOfSpace;
        ++i;
    }
    // 由空格数计算新串位置。若超出范围则返回
    int newlength = originLength + 2 * numberOfSpace;
    if (newlength > length)
        return str;

    cout << newlength << endl << originLength << endl;

    int indexOfOrigin = originLength;
    int indexOfnew = newlength;
    // 当扫描到首部,或者空格处理完毕
    while (indexOfOrigin >= 0 && indexOfnew > indexOfOrigin)
    {
        // 当遇空格时,indexOfnew多走两位
        // 走完空格两者相遇
        if (str[indexOfOrigin] == ' ')
        {
            str[indexOfnew--] = '0';
            str[indexOfnew--] = '2';
            str[indexOfnew--] = '%';
        }
        else
        {
            // 普通字符直接赋值,均往前走一位
            str[indexOfnew--] = str[indexOfOrigin];
        }
        // 每次迭代indexOfOrigin都往前走一位
        --indexOfOrigin;
    }
    return str;
}

int main()
{
    char str[100] = {"We are happy."};
    char str[100] = {" "};
    cout << str << endl;
    cout << replace(str, 100) << endl;

    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值