将一个字符串里的空格替换成%20。
常规思路:从前往后移动字符串,遇到空格将其替换,问题是每遇到一次,空格后面的字符串就要被移动一次,假设字符串长度是n,时间效率是O(n的平方);
正确思路:从后往前移动字符串,计算出替换过后字符串的位置,准备两个指针P1和P2,P1指向原始字符串的末尾,P2指向替换后字符串的末尾,然后将P1指向的字符复制到P2指向的位置,复制完成后两个指针向前,直到P1遇到空格,P2此时向前写入%20,P1向前一格。循环到P1和P2指向同一个位置,结束。时间效率为O(n)。
代码如下:
#include<iostream>
using namespace std;
void ReplaceBlank(char str[],int len)
{
if (str==NULL&&len<=0)
{
return;
}
int originalLength=0;
int blankNum=0;
int i=0;
while (str[i]!='\0')
{
originalLength++;
if (str[i]==' ')
{
blankNum++;
}
i++;
}
int newLength=originalLength+blankNum*2;
if (newLength>len)
{
return;
}
int indexOfOriginal=originalLength;
int indexOfNew=newLength;
while (indexOfOriginal>=0&&indexOfNew>indexOfOriginal)
{
if (str[indexOfOriginal]==' ')
{
str[indexOfNew--]='0';
str[indexOfNew--]='2';
str[indexOfNew--]='%';
}
else
{
str[indexOfNew--]=str[indexOfOriginal];
}
indexOfOriginal--;
}
}
void Test(char str[],int len,char expect[])
{
const int length=len;
ReplaceBlank(str,len);
if(str==NULL&&expect==NULL)
{
printf("pass\n");
}
else if (strcmp(str,expect)==0)
{
printf("pass\n");
}
else
printf("failed\n");
}
void Test1()
{
const int length=100;
char str[length]="hello world";
Test(str,length,"hello%20world");
}
void Test2()
{
const int length=100;
char str[length]="";
Test(str,length,"");
}
void Test3()
{
Test(NULL,0,NULL);
}
int main()
{
Test1();
Test2();
Test3();
cin.get();
}
小结:合并连个数组(包括字符串)时,如果从前往后复制每个数字(或支付宝)需要重复移动数字(或字符)很多次,我们可以考虑从后往前复制,这样就能减少移动的次数,从而提高效率。