剑指offer刷题之面试题4---------替换空格

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

常规思路:从头到尾扫描字符串,每一次碰到空格,必须先把空格后面的所有字符都后移两个字节(否则就有两个字符被覆盖了),然后再替换空格。此种方法,对于长度为n的字符串来说,算法的时间复杂度为O(n2)

为了减少移动次数,换一种思路:从前向后替换改为从后向前替换,时间复杂度变为O(n)

实现步骤:

(1)先遍历一次字符串,统计出字符串中空格的总数,并由此计算出替换之后的字符串的总长度=原来的长度+空格数*2

(2)从字符串后面开始复制和替换。准备两个指针P1和P2,P1指向原始字符串的末尾,P2指向指向替换之后的字符串的末尾。 向前移动指针P1,逐个把它指向的字符复制到P2指向的位置,直到碰到第一个空格为止。
(3)碰到第一个空格,把P1向前移动一格,P2移动三格(因为插入的字符串%20长度是3),在P2之前插入字符串“%20”。接着向前复制,直到碰到第二个空格,同理。

(4)当P1和P2指向同一位置,表明所有空格都已经替换完毕。可以分析出,所有的字符只复制(移动)一次,因此这种方法的时间复杂度是O(n)

代码如下:

void ReplaceBlank(char string[], int length)  //length为字符数组string的总容量,大于或等于字符串string的实际长度
{
	if(string == nullptr || length <=0)
		return;                        //用于返回类型为void的函数,return语句是为了引起函数的强制结束,这种用法类似于循环结构中的break语句的作用。

	int originalLength = 0;          //定义变量originalLength为字符串string的实际长度,初始值为0
	int numberofBlank = 0;           //定义变量numberofBlank为字符串string的空格数,初始值为0 

	int i = 0;
	while(string[i] != '\0')      //遍历字符串,统计出字符串中空格的总数,并存于变量numberofBlank
	{
		++ originalLength;
		if(string[i] == ' ')
			++ numberofBlank;
		++ i;
	}
	
	int newLength = originalLength + numberofBlank * 2;    //newLength 为把空格替换成'%20'之后的字符串长度
	if(newLength > length)          //若新的字符串长度大于字符数组string的总容量则无法插入
		return;

	int p1 = originalLength;      //此处就像前面分析的,定义了变量p1和p2,虽然不是指针,但用在string数组中就相当于指针p1和p2,
	int p2 = newLength;           //string[p1]初始值指向原始字符串的末尾,string[p2]初始值指向替换的字符串的末尾
	while(p1 >= 0 && p2 > p1)     //放字符
	{
		if(string[p1] == ' ')     //判断string[p1]是否指向空格,若是将p2依次向前移动,进行替换
		{
			string[p2 --] == '0';
			string[p2 --] == '2';
			string[p2 --] == '%';
		}
		else                      //若string[p1]指向的不是空格,则把string[p1]指向的字符复制到string[p2]中,并将p2向前移动一位
		{
			string[p2 --] = string[p1];
		}
		-- p1;         //每次操作完,将p1向前移动一位
	}
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值