剑指offer--替换空格

来源:互联网 发布:淘宝3c证书编号在哪里 编辑:程序博客网 时间:2024/06/15 17:28

记录《剑指offer》上的算法题。完整的代码例子可以在我的Github。

这是一道有关字符串的问题。首先在C/C++中,会把常量字符串放到单独的一个内存区域中,当几个指针赋值给相同的常量字符串时,它们实际上会指向相同的内存地址;但如果用常量内存初始化数组,数组的地址是不相同的。

下面给出替换空格的题目:

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

在网络编程中,对于含有特殊字符的URL参数,如空格,”#“等,可能导致服务器端无法获得正确的参数值。我们需要将这些特殊符号转换成服务器可以识别的字符,替换的规则是在’%’后面跟上ASCII码的两位十六进制的表示。比如空格的ASCII码是32,即十六进制的0x20,因此空格被替换成”%20”。

这里首先需要分两种情况,第一种是在原来的字符串上做替换;第二种是创建新的字符串并在新的字符串上做替换。现在假设是第一种情况,在原来的字符串上做替换并保证输入的字符串后面留有足够的空余内存。

最直观的做法是从头到尾扫描字符串,每一层碰到空格字符的时候做替换,由于需要将1个字符替换成3个字符,所以每次替换的时候,都要将空格后面的字符都往后移动两个字节,否则就有两个字符被替换了。因此,这种做法的时间复杂度是O(n2)

上述做法是从前往后替换,现在可以换个思路,从后往前进行替换。首先是先遍历一遍字符串,计算字符串中空格的总数,由此计算出替换之后字符串的总长度,这里是每替换一个空格就需要增加两个字节的长度,因此替换之后的字符串长度应该是原来的长度加上两倍的空格数目。然后从后面开始复制和替换空格,需要准备两个指针P1和P2,P1指向当前字符串末尾,P2指向替换之后的字符串的末尾,然后向前移动P1,逐个把它指向的字符复制到P2指向的位置,而遇到空格的时候,P2就需要向前移动3格,因为需要复制过来的是3个字符,而P1还是移动一位。而当P2和P1都指向同一个位置的时候,说明所有空格都替换完毕了。

这种做法的时间复杂度是O(n),效率是远高于第一种做法,下面给出这种做法的代码实现和测试例子。

#include<iostream>using std::cout;using std::endl;using std::cin;// 替换空格,length是字符数组string的总容量void ReplaceBlank(char string[], int length){    if (string == NULL || length <= 0){        return;    }    // 字符串string的实际长度    int originLength = 0;    int numberOfBlank = 0;    int i = 0;    // 统计空格的数量和字符的数量    while (string[i] != '\0'){        ++originLength;        if (string[i] == ' ')            ++numberOfBlank;        ++i;    }    // 替换空格后的字符串新长度    int newLength = originLength + numberOfBlank * 2;    if (newLength > length)        return;    int indexOfOriginal = originLength;    int indexOfNew = newLength;    while (indexOfOriginal >= 0 && indexOfNew > indexOfOriginal){        if (string[indexOfOriginal] == ' '){            string[indexOfNew--] = '0';            string[indexOfNew--] = '2';            string[indexOfNew--] = '%';        }        else{            string[indexOfNew--] = string[indexOfOriginal];        }        indexOfOriginal--;    }}// 测试int main(void){    char str[10] = " hello";    char str2[10] = "he llo";    char str3[10] = "hello ";    char str4[30] = "We  are  happy.";    char str5[30] = "helloWorld.";    char *str6 = NULL;    char str7[10] = "";    char str8[10] = " ";    char str9[20] = "     ";    // 空格位于字符串的最前面    cout << "origin: " << str;    ReplaceBlank(str, 10);    cout << ",--> " << str << endl;    // 空格位于字符串的最后面    cout << "origin: " << str2;    ReplaceBlank(str2, 10);    cout << ",--> " << str2 << endl;    // 空格位于字符串的中间    cout << "origin: " << str3;    ReplaceBlank(str3, 10);    cout << ",--> " << str3 << endl;    // 字符串中有多个连续空格    cout << "origin: " << str4;    ReplaceBlank(str4, 30);    cout << ",--> " << str4 << endl;    // 输入的字符串没有空格    cout << "origin: " << str5;    ReplaceBlank(str5, 30);    cout << ",--> " << str5 << endl;    // 字符串是空指针    ReplaceBlank(str6, 10);    // 字符串是空字符串    cout << "origin: " << str7;    ReplaceBlank(str7, 10);    cout << ",--> " << str7 << endl;    // 字符串只有一个空格字符    cout << "origin: " << str8;    ReplaceBlank(str8, 10);    cout << ",--> " << str8 << endl;    // 字符串中只有多个连续空格    cout << "origin: " << str9;    ReplaceBlank(str9, 20);    cout << ",--> " << str9 << endl;    system("pause");    return 0;}

这种从后往前复制的思路还可以用在合并两个数组的情况。

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 孩子被同学打了家长该怎么办? 孩子把同学打了打人家长该怎么办 孩子和同学发生矛盾家长该怎么办 孩子同学给孩子要东西家长该怎么办 如果遇到不讲理的孩子和家长怎么办 孩子调皮又被老师留校了怎么办 孩子拼音f和sh发音不清怎么办 自己在家生的孩子怎么办出生证明 在家念地藏经招来众生不走怎么办 家是济宁孩子上学想在济南上怎么办 高一孩子成绩严重下滑家长怎么办 商铺租客不交租金又不搬走怎么办 考试试卷找不到了明天要交怎么办 8个月宝宝不爱吃蔬菜泥怎么办 5个月的宝宝拉肚怎么办 一岁宝宝大便拉不出来怎么办 八个月宝宝便秘拉不出来怎么办 10个月宝宝大便拉水怎么办 4个月的孩子大便拉水怎么办 五个多月宝宝大便拉水怎么办 七个月宝宝大便还没成行怎么办 宝宝一岁了还没长牙怎么办 宝宝什么都会就差不会独占怎么办 两岁宝宝肚子不舒服还吐怎么办 两岁宝宝吃坏肚子吐怎么办 1岁半儿童牙烂了怎么办 一岁宝宝吃了就吐怎么办 两岁宝宝龋齿门牙掉了怎么办 一岁宝宝冻着了呕吐怎么办 两岁宝宝喉咙有痰呼呼响怎么办 1岁宝宝吐的水水怎么办 宝宝吐了5 6次了怎么办 7岁儿童吃了就吐怎么办 狗狗拉稀呕吐不吃饭只喝水怎么办 宝宝吃坏肚子上吐下泄怎么办 一岁宝宝又吐又拉怎么办 八个月宝宝吃什么吐什么怎么办 九个月宝宝吃什么吐什么怎么办 三岁宝宝吃什么吐什么怎么办 2岁宝宝又拉又吐怎么办 6岁儿子又吐又拉怎么办