剑指offer--替换空格

记录《剑指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;
}

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/409001.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java打开word文件名乱码怎么解决_Word文档乱码怎么办?解决Word文档乱码的几种常见方法...

最近Word经常出现问题&#xff0c;双击打开后就弹出“文件转换”的对话框&#xff0c;让选择装载此文件时要使用的编码&#xff0c;选择了简体中文&#xff0c;打开文档后还是乱码&#xff0c;遇到这种情况我们应该怎么办呢?解决方法一&#xff1a;把原来的文档另存为*.rtf格式…

剑指offer--从尾到头打印链表

记录来自《剑指offer》的算法题目 链表应该是面试时被提及最频繁的数据结构&#xff0c;它的结构简单&#xff0c;由若干个结点连接成链状结构&#xff0c;其创建、插入结点、删除结点等操作都只需要20行左右的代码就能实现&#xff0c;其代码量比较适合面试。 假设单链表的结…

java序列化表单同步请求_Ajax serialize() 表单进行序列化方式上传文件

通过传统的 form 表单提交的方式上传文件上传文件&#xff1a;不过传统的 form 表单提交会导致页面刷新&#xff0c;但是在有些情况下&#xff0c;我们不希望页面被刷新&#xff0c;这种时候我们都是使用 Ajax 的方式进行请求的。使用 serialize() 对 form 表单进行序列化提交$…

Linux下Nginx的安装和简单管理

nginx下载 http://nginx.org/download/ http://www.2cto.com/os/201206/136381.html转载于:https://www.cnblogs.com/jphp/archive/2013/04/01/2993403.html

谈 数学之美 和 看见

两本书本来是没有什么交集的。 而对于我而言,交集可能是我最近这两本书都买了。闲暇的时间还是会翻一翻的。看见这本书是今天中午到的。发现现在的当当比以前在书的保养上比以前好像好了一点。几本书都是给包住了,防止弄坏了拐角。 两本书我都很喜欢,今天到的书也是立刻就读了起…

剑指offer--用两个栈实现队列

记录《剑指offer》上的算法题。 题目描述如下&#xff1a; 用两个栈实现一个队列&#xff0c;队列的声明如下&#xff0c;请实现它的两个函数appendTail和deleteHead&#xff0c;分别完成在队列尾部插入结点和在队列头部删除结点的功能。 队列的声明如下&#xff1a; templat…

剑指offer--旋转数组的最小数字

记录来自《剑指offer》上的算法题。 题目描述如下&#xff1a; 把一个数组最开始的若干个元素搬到数组的末尾&#xff0c;我们称之为数组的旋转。输入一个递增排序的数组的一个选择&#xff0c;输出旋转数组的最小元素。例如数组{3,4,5,1,2}是{1,2,3,4,5}的一个旋转&#xff0…

python 合并excel 自动更新_手把手教你4种方法用Python批量实现多Excel多Sheet合并

一、前言大家好&#xff0c;我是崔艳飞。前两天给大家分享了Python自动化文章&#xff1a;手把手教你利用Python轻松拆分Excel为多个CSV文件&#xff0c;而后在Python进阶交流群里边有读者遇到一个问题&#xff0c;他有很多个Excel表格&#xff0c;他需要对这些Excel文件进行合…

jQuery布局插件UI Layout简介

UI Layout是一种基于jQuery的布局框架&#xff0c;项目主页http://layout.jquery-dev.net/。该框架的参考原型是ExtJS的border-layout&#xff0c;因此十分适用于将原有使用ExtJS的项目改造成jQuery项目。其核心是一个大小自适应的中心面板&#xff08;必选&#xff09;&#x…

淘到了一个不错的TF卡读卡器

最近换手机的时候一时冲动败了个32G的TF卡。买后又觉得手机存储空间还比较充裕&#xff0c;暂时用不上&#xff0c;便打算套个读卡器当U盘用。最开始我用的是以前买手机的时候送的一个读卡器&#xff0c;但其兼容性很差&#xff0c;在以前的那个8G的卡里还能勉强用用&#xff0…

剑指offer--斐波那契数列

记录来自《剑指offer》的算法题。 题目如下&#xff1a; 写一个函数&#xff0c;输入n&#xff0c;实现斐波那契数列的第n项。 斐波那契数列的定义如下&#xff1a; f(n)⎧⎩⎨01f(n−1)f(n−2)n0n1n>1f(n) = \begin{cases} 0 & n=0 \\ 1 & n=1 \\ f(n-1) + f(n-2…

java jdbc6_Java学习-JDBC

JDBC1、数据库驱动应用程序通过驱动连接到数据库&#xff0c;进而操作数据库。2、JDBC简化开发人员对数据库的操作&#xff0c;提供了一个java操作数据库的规范&#xff0c;俗称JDBC对于程序猿&#xff0c;只需要学习JDBC提供的接口。java.sqljavax.sqlpublic class DemoJdbc01…

Unity3D For Android 开发教程【转http://game.ceeger.com/Unity/Doc/2011/Unity3D_For_Android.html】...

Unity3D For Android 开发教程 Date:2011-08-01 04:33我自认为抵挡诱惑的能力还是很强大的&#xff0c;关键的时候还能把持住自己。今天逛了一下南京的丹凤街&#xff0c;终于受不住Android这美眉的诱惑。她虽脸蛋不怎么滴&#xff0c;但身材火热&#xff0c;且性感&#xff0c…

剑指offer--二进制中1的个数

记录来自《剑指offer》上的算法题。 题目如下&#xff1a; 请实现一个函数&#xff0c;输入一个整数&#xff0c;输出该数二进制表示中1的个数。例如把9表示成二进制是1001&#xff0c;有两位是1&#xff0c;因此如果输入9&#xff0c;函数输出是2。 这道题目的一个基本思路是…