目录
(2)原数组的长度小于替换后的长度,需要额外创建一个数组保存替换后字符串。
字符串替换有两种情况,一种是把一个空格换成多个字符,另一种是把多个空格换成一个空格。
一、一个换多个
题目:请实现一个函数,把字符中的每个空格替换成"%20".
(1)原数组的长度大于替换后的长度。
思路:额外定义一个数组 ,如果是字符,直接拷贝,如果是空格,就把'%','2','0'分别复制过去,最后用拷贝函数将数组里的字符串拷贝到元素组,最后释放这个数组,时间复杂度为O(n),空间复杂度为O(n)。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
using namespace std;
char* StringReplace(char * arr)
{
int len = strlen(arr);
int newlen = 0;
int count = 0;
for(int i=0;i<len;i++)
{
if(arr[i] == ' ')
{
count += 1;
}
}
newlen = 2*count +strlen(arr);
char *des = (char *) malloc (sizeof(char) * (newlen+1));
//char * res = des;
for(int i = 0,j =0 ;i < len;i++,j++)
{
if(arr[i] == ' ')
{
des[j] = '%';
des[++j] = '2';
des[++j] = '0';
}
else
{
des[j] = arr[i];
}
}
des[newlen] = '\0';
strcpy(arr,des);
free(des);
return arr;
}
int main()
{
char arr[100] = "a b c";//len = 5 加'\0'为6
StringReplace(arr);
printf("%s\n",arr);
return 0;
}
上面的做法空间复杂度可以降低,直接在原数组里操作,以防覆盖数据,所以将字符串数组从后往前拷贝,碰到空格,就把'0','2','%'赋值进去,如果是字符就直接赋值进去。
优化代码:
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<string.h>
char* Stringreplace(char *str,int len)
{
assert(str != NULL && len > 0);
int oldtlen = strlen(str);//旧的字符串长度
int newlen = 0;//新的字符串长度
int count = 0;//统计空格个数
for(int i = 0;i<oldlen;i++)
{
if(str[i] == ' ')
{
count ++;
}
}
newlen = count*2+oldlen;
if(len <newlen || newlen == oldlen)
{
return str;
}
for(int i = oldlen-1, j = newlen -1;i>= 0;i--,j--)
{
if(str[i] != ' ' )
{
str[j] = str[i];
}
else
{
str[j] = '0';
str[--j] = '2';
str[--j] = '%';
}
}
return str;
}
int main()
{
char str[20] = "a b c";
int len = 20;
printf("%s\n",str);
char * des = Stringreplace(str);
printf("%s\n",des);
}
(2)原数组的长度小于替换后的长度,需要额外创建一个数组保存替换后字符串。
思路和上面的同理。时间复杂度为O(n),空间复杂度为O(n)。
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<string.h>
char* Stringreplace(char *str)
{
assert(str != NULL);
int len = strlen(str);//旧的字符串长度
int newlen = 0;//新的内存大小
int count = 0;//统计空格个数
for(int i = 0;i<len;i++)
{
if(str[i] == ' ')
{
count ++;
}
}
newlen = count*2+len;
printf("%d\n",newlen);
char * des = (char *) malloc ( sizeof(char) * (newlen+1));
des[newlen] = '\0';
for(int i = len-1, j = newlen -1;i>= 0;i--,j--)
{
if(str[i] != ' ' )
{
des[j] = str[i];
}
else
{
des[j] = '0';
des[--j] = '2';
des[--j] = '%';
}
}
return des;
}
int main()
{
char str[20] = "a b c";
printf("%s\n",str);
char * des = Stringreplace(str);
printf("%s\n",des);
free(des);
}
二、多个换一个
题目:请实现一个函数,把字符串中的多个空格变成一个空格。
思路:在原数组里操作,因为是多个空格变成一个空格,所以新的数组长度一定等于或者小于元数组的长度。为防止覆盖数组,从左往右开始拷贝。定义两个变量,i和j,碰到两个空格相连,i++,j不动,其他情况数组i下标的值赋给j下标的值。
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<string.h>
char* Stringreplace(char* str)
{
assert(str != NULL);
int len = strlen(str);
int i = 0,j = 0;
for(;i<len;i++)
{
if( !(str[i] == ' ' && str[i+1] == ' '))
{
str[j] = str[i];
j++;
}
}
str[j] = '\0';
return str;
}
int main()
{
char str[100] = "a b c d ";
Stringreplace(str);
printf("%s\n",str);
return 0;
}
三、拓展
题目:将字符串里的"*"都放到前面,将字符按顺序输出。
思路:在原数组里操作,所以要从后往前拷贝。先把*的个数统计出来,然后从后往前拷贝,碰到*不拷贝,继续往下遍历,直到原数组的字符已经全部拷贝,将前面的全部拷贝成*。
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<string.h>
char* Stringreplace(char * str)
{
int count = 0;
int len = strlen(str);
int j = len-1;
for(int i = 0;i<len;i++)
{
if(str[i] == '*')
{
count ++;
}
}
for(int i = len-1;i>=0;i--)
{
if(str[i] !='*')
{
str[j] = str[i];
j--;
}
}
for(j = count-1;j>= 0;j--)
{
str[j] = '*';
}
return str;
}
int main()
{
char str[100] = "a*b*c";
printf("%s\n",str);
Stringreplace(str);
printf("%s\n",str);
return 0;
}