剑指offer-字符串学习笔记
一、字符串相关特性
C/C++中每一个字符串都是以’\0’作为结尾,这样我们就可以很方便的找到字符串的最后尾部。正因为这个特点每一个字符串都需要一个额外字符的开销。
为了节省内存,C/C++把常量字符串放到单独的一个内存区域。当几个指针赋值给相同的常量字符串时,他们实际上会指向相同的内存地址。但是,如果使用常量内存初始化数组,情况有所不同,比如下面的代码。
int main()
{
char str1[] = "hello world";
char str2[] = "hello world";
char *str3 = "hello world";
char *str4 = "hello world";
if(str1 == str2){
printf("str1 and str2 are same.\n");
}
else
{
printf("str1 and str2 are not same.\n");
}
if(str3 == str4)
{
printf("str3 and str4 are same\n");
}
else
{
printf("str3 and str4 are not same.\n");
}
return 0;
}
str1 和 str2 是两个字符串数组,我们会为他们分配两个长度为12字节的空间,并把"hello world"的内容分别复制到数组中去。这是两个初始地址不同的数组,因此str1和str2的值也就不同,所以输出的第一行是"str1 and str2 are not same"
str3 和 str4是两个指针,我们无需为他们分配内存以存储字符串的内容,而只需要把他们指向hello world在内存中的地址就可以。所以str3与str4指向的是同一个地址。输出的第二行就是"str3 and str4 are same"
二、面试题五:替换空格
思路:首先遍历一遍字符串,这样就可以统计出字符串中空格的字数,同时也统计该字符串的字符个数,然后计算新的字符串长度,重新设定字符串长度,新的字符串长度等于原来的长度加上2 * 空格数目。之后,准备两个指针,p1指向原始的字符串末尾(‘\0’),p2指向新的字符串末尾,接下来移动指针p1,如果当前指向的字符不是空格,那么就将该字符复制到p2指向的位置,然后继续向下移动p1,如果p1指向的字符是一个空格,那么将p2位置填充’%20’,p2继续向下移动,p1移动一格。(由于在原字符串上进行改动,所以p1指向的那些字符会被p2的赋值’%20’字符给覆盖掉)
class Solution {
public:
string replaceSpace(string s) {
int originalLength = 0;// 原始字符串长度
int numberOfBlank = 0;// 统计空格数
int i = 0;
while(s[i] != '\0')
{
originalLength++;
if(s[i] == ' ')
{
numberOfBlank++;
}
i++;
}
// 计算替换之后的长度
int newLength = originalLength + numberOfBlank * 2;
s.resize(newLength);
// 设置两个指针 分别指向原来的字符串末尾 以及新的字符串末尾
int p1 = originalLength;// 这是p1指向的其实是'\0'
int p2 = newLength;// p2始终指向空格处
// 设定判断条件p2 > p1 说明如果p2 <= p1 此时指针其实已经重合了填补完毕 只存在p2 = p1 没有p1 > p2
while(p1 >= 0 && p2 > p1)
{
if(s[p1] != ' ')
{
s[p2] = s[p1];
p2--;// p2再次指向空格
p1--;// p1向下继续寻找空格
}
else
{
// p1指向空格
// p2 此时用%20 填充 同时记得p2--
// p1-- 继续想寻找空格
s[p2--] = '0';
s[p2--] = '2';
s[p2--] = '%';
p1--;
}
}
return s;
}
};