键指offer——面试题5:字符串之替换空格(p49-54)

替换空格

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

分析:
我们这题就先假设所给的字符串长度够长,足以用来将全部空格替换成"%20",不然的话替换的时候就会覆盖原有的字符串喽。
在这里插入图片描述
以string = “We are happy.”为例子,如图所示:原始string空格处插入"%20"之后就变成了新的字符串newString。

在操作的时候我们先计算出原始string的长度为14(包括结尾处的'\0'字符),每替换一个空格总的长度就会增加2,那新的字符串newString的长度就为14+2*空格数=14+2*2=18

我们在替换的时候就倒着来进行替换,若没碰见空格' ',就正常向后移动即可;若碰到空格,则分别插入'0','2','%'即可,直到碰见第一个字符为止。

这样对于每个字符只需要复制(移动)一次即可,因此时间效率为O(n)。

pass:若从前往后进行替换,假设字符串长度为n,对于每个空格需要移动后面O(n)个字符,因此对于含有O(n)个空格的字符串来说,总的时间效率为O(n^2),显然时间复杂度大。
备注:O表明某个算法的耗时/耗空间与数据增长量之间的关系。

考察队内存覆盖是否有警惕性 ,思维能力,是否能找到最优处理方式。。

伪代码:

void replaceBlank(char string[], int length)
{
	//length是一个长度足够大的值;
	//先特殊处理
	数组指针为空指针或者这个长度小于等于0了,直接返回;
	
	//处理
	遍历这个数组:
		若碰见空格:记录空格的个数;
		若碰见字符:记录字符的个数;
	计算数组内空格替换后的数组长度值得到newlen;
	若这个值大于最初的length,就表明之后不能正常输出替换后的数组;
	//开始替换
	若newlen不为0:
		若碰见空格:
			在这个位置插入字符串%20;
		否则:
			将原始的字符进行复制;
		--newlen;
}

代码:

#include<iostream>
#include<string>
using namespace std;

void replaceBlank(char string[], int length)
{
	//假定这个string的长度满足将空格替换后的长度
	//注意这里的length为string的总容量

	//特殊处理
	if(string==nullptr || length<=0)
		return ;
	int num=0, origianlLen=0;
	for(int i=0;i<=length;i++)
	{
		if(string[i] == ' ')
			++num;
		if(string[i] != '\0')
			++origianlLen;
	}
	int newLen = origianlLen + 2*num;
	if(newLen > length)
		return ;

	int indexOfNewLen = newLen;
	int indexOfOrigianlLen = origianlLen;
	
	while(indexOfOrigianlLen>=0 && indexOfNewLen>indexOfOrigianlLen)
	{
		if(string[indexOfOrigianlLen] == ' ')
		{
			string[indexOfNewLen--] = '0';
			string[indexOfNewLen--] = '2';
			string[indexOfNewLen--] = '%';
		}
		else
		{
			string[indexOfNewLen--] = string[indexOfOrigianlLen];
		}

		--indexOfOrigianlLen;
	}

}

int main()
{
	const int length = 20;
	char string[length] = "We are happy.";
	replaceBlank(string, length);

	return 0;
}

举一反三:
对于两个已排好顺序的数组互相插入值时也是,从尾向头插入操作比较好;
合并两个数组也是。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值