剑指offer:替换空格
问题:
实现一个函数,将字符串中的每个空格替换成"%20""。
如:输入“We are happy.”, 则输出 "We%20are%20happy"
首先有两种方式:一是在原来的字符串上面进行替换,就有可能覆盖子啊该字符串后面的内存。
另一种是创建新的字符串进行替换,那么可以分配足够多的内存。
现在主要考虑第一种方式。
思路:
1.从前向后进行替换:假设字符串的长度是n,对每个空格字符,需要向后面移动O(n)
个字符,所以总的时间效率是O(n^2).
2.从后向前进行替换:
首先遍历一遍计算字符串中空格的个数,并由此计算出替换后的字符串的总长度。每替换一个空格,
长度增加2,因此替换后的字符串的长度等于原来的长度加上 2 × 空格的数目。然后从后向前替换
空格,具体见图:
实现:
已经在牛客网通过。
class Solution {
public:
//str为给定的字符数组的头指针, length为str的容量。
void replaceSpace(char *str,int length) {
//异常处理
if (str == NULL || length < 0) return;
//首先要得到变化后的字符串的长度(包括'\0')
int original_length = 0;
int present_length = 0;
int blank = 0;
while(str[original_length] != 0)
{
if (str[original_length] == ' ') blank++;
original_length++;
}
present_length = original_length + 2 * blank;
//异常处理
if (present_length > length) return;
// printf("%d\n", blank);
// printf("%d\n", original_length);
// printf("%d\n", present_length);
int present_index = present_length;
int original_index = original_length;
// printf("%d\n", original_index);
// printf("%d\n", present_index);
while(present_index != original_index)
{
if (str[original_index] == ' ')
{
str[present_index--] = '0';
str[present_index--] = '2';
str[present_index--] = '%';
original_index-=1;
}
else{
str[present_index--] = str[original_index--];
}
}
}
};
注意:自己在测试的时候,不要用字符指针初始化,因为字符指针指向的字符内容不能进行修改,而要用字符数组。
一点关于二者的对比放在下面:
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
/* C/C++ 中的每个字符串都以 '\0' 结尾,小心会造成越界,每个字符串都有一个额外的字符开销。
为了节省内存,C/C++将常量字符串放到一个单独的内存区域。当几个指针赋给相同的字符串
时,它们实际上会指向相同的内存地址。但用常量内存初始化数组,情况却有所不同。 */
int main()
{
char str1[] = "hello world";
char str2[] = "hello world";
//str1 和 str2 是两个字符串数组,为它们分配两个长度为12字节的空间,并将hello world
//复制进去。这是两个初始地址不同的数组,因此str1和str2的值不同。
//str3和str4是两个指针,我们无需为他们分配内存以储存字符串的内容,只需要把它们指向hello
//world在内存中的地址,常量字符串在内存中只有一个拷贝,因此str3和str4得到的结果是相同的。
char *str3 = "hello world";
//双引号做了三件事:1.在常量区申请了空间。2.在字符串的结尾加上了'\0'。3.返回地址
char *str4 = "hello world";
cout << (str1 == str2) << endl; //== 是比较两个数,也就是在%d下的值,str1、str2的value是首字母的地址,不相同
cout << "str1 =" << str1 << "\n" << "str2 = " << str2 << endl;
cout << "*str1 ="<<*str1 << "\n"<< "*str2 =" <<*str2 << endl;
cout << str3 << "\n" << *str3 << endl;
char str5[10] = "abcdefg"; //这样初始化可以
char str6[10]; //一旦开始没有初始化,就不能这样赋值了
//str6 = "nice";
char *str8; //字符指针可以这样赋值
str8 = "abcdef";
//指针变量指向的字符串内容不能修改
char *p = "hello";
//*p = 'a'; 这样是错误的
//这样可以,因为指针变量的值可以修改
char ch = 'b';
p = &ch;
printf("%c\n", *p);
//字符串数组内容可以修改,但字符串数组所代表字符串的首地址不能修改
//初始化
//字符串数组
char str9[20];
scanf("%s", str9);
cout << str9 << endl;
//字符指针
char *str10 = NULL;
str10 = (char*)malloc(10);
scanf("%s", str10);
cout << str10 << endl;
return 0;
}
输出的结果是: