原题:
请实现一个函数,把字符串中的每个空格替换成"%20",例如输入"we are happy.",则输出"we%20are%20happy";
分析:
看到这个问题第一感觉很简单,就是简单的字符串替换问题,很简单的方法就能实现。但是当细心一想,就会发现其时间效率是很重要的一个要解决方面。
最原始的想法是从头到尾遍历其整个数组,遇到空格就转化,当把一个空格转化成三个字符就相当于后面的字符需要向后移动,这时就会想到,每遇到一个空格,就需要往后移动后面的数组中的内容,这样他的时间复杂度就成了O(n2)。这肯定是不行的。
那么还有其他思路吗?
1,如果可以使用辅助内存,那这个题目也很简单,new一个新的数组,来存放转化之后的字符串,做两个指针p1,p2,p1指向原始字符串的首地址,p2指向新的。遇到空格p2往后移动三个,并将其相应的转化成要转化的字符。
2,如果不能使用辅助内存,就只能允许在原始的数组上向后扩充,并且数组足够大。那么怎么办?
其实遇到这种字符串转换的,就要形成思维定式了,试一下从后往前遍历数组。先遍历一边数组,计算出数组的长度和空格数目,那么最后数组的长度就newLength = oldLength + numBlank*2(一个字符被替换成了三个字符)。这样再设置两个指针,一个指向当前数组的最后一个字符,另一个指向最终长度的最后一个指针,剩下的方法就同1了。
代码:
#include <iostream>
using namespace std;
void ReplaceBlank(char *str,int length)
{
if(str == NULL || length <= 0)
return ;
int numBlank=0,lengthOfStr=0;
int i=0;
while(str[i] != '\0')
{
++lengthOfStr;
if(str[i] == ' ')
++numBlank;
++i;
}
int lengthOfEnd = lengthOfStr + numBlank * 2 ;
int p1 = lengthOfStr;
int p2 = lengthOfEnd;
if(lengthOfEnd > length)
///这个判断表示如果替换完之后之前的数组不够长
return ;
str[lengthOfEnd+1] = '\0';
while(p1>=0 && p2 >=0)
{
if(str[p1] == ' ')
{
str[p2--] = '0';
str[p2--] = '2';
str[p2--] = '%';
}
else
{
str[p2--] = str[p1];
}
p1--;
}
}
int main()
{
char str[20] = " ";
ReplaceBlank(str,20);
cout<<str<<endl;
return 0;
}
using namespace std;
void ReplaceBlank(char *str,int length)
{
if(str == NULL || length <= 0)
return ;
int numBlank=0,lengthOfStr=0;
int i=0;
while(str[i] != '\0')
{
++lengthOfStr;
if(str[i] == ' ')
++numBlank;
++i;
}
int lengthOfEnd = lengthOfStr + numBlank * 2 ;
int p1 = lengthOfStr;
int p2 = lengthOfEnd;
if(lengthOfEnd > length)
///这个判断表示如果替换完之后之前的数组不够长
return ;
str[lengthOfEnd+1] = '\0';
while(p1>=0 && p2 >=0)
{
if(str[p1] == ' ')
{
str[p2--] = '0';
str[p2--] = '2';
str[p2--] = '%';
}
else
{
str[p2--] = str[p1];
}
p1--;
}
}
int main()
{
char str[20] = " ";
ReplaceBlank(str,20);
cout<<str<<endl;
return 0;
}
注意:
1,空指针的异常判断
2,转化之后可能超出原数组的异常
相关题目:
有两个排序数组,A1,A2,内存在A1的末尾有足够多的空余空间容纳A2。请实现一个函数,把A2中的所有数字插入到A1中并且所有的数字是排序的
解决思路:
从尾到头比较A1和A2中的数字,并把较大的数字复制到A1的合适位置。
代码:
#include <iostream>
using namespace std;
void Merger(int *a,int *b,int lenA,int lenB)
{
if(a == NULL || b == NULL || lenA <= 0 || lenB <= 0)
return ;
int length = lenA + lenB+1;
while(lenA>=0 && lenB>=0 && length>=lenA)
{
if(a[lenA]>b[lenB])
a[length--] = a[lenA--];
else if(a[lenA] < b[lenB])
a[length--] = b[lenB--];
else
{
a[length--] = a[lenA--];
a[length--] = b[lenB--];
}
}
while(lenA>=0 && length>=0)
a[length--] = a[lenA--];
while(lenB>=0 && length>=0)
a[length--] = b[lenB--];
}
int main()
{
int a[10] = {1,2,4};
int b[4] = {3,5,6};
Merger(a,b,2,2);
for(int i=0;i<10;i++)
cout << a[i] << " ";
cout<<endl;
return 0;
}
using namespace std;
void Merger(int *a,int *b,int lenA,int lenB)
{
if(a == NULL || b == NULL || lenA <= 0 || lenB <= 0)
return ;
int length = lenA + lenB+1;
while(lenA>=0 && lenB>=0 && length>=lenA)
{
if(a[lenA]>b[lenB])
a[length--] = a[lenA--];
else if(a[lenA] < b[lenB])
a[length--] = b[lenB--];
else
{
a[length--] = a[lenA--];
a[length--] = b[lenB--];
}
}
while(lenA>=0 && length>=0)
a[length--] = a[lenA--];
while(lenB>=0 && length>=0)
a[length--] = b[lenB--];
}
int main()
{
int a[10] = {1,2,4};
int b[4] = {3,5,6};
Merger(a,b,2,2);
for(int i=0;i<10;i++)
cout << a[i] << " ";
cout<<endl;
return 0;
}