- 字符串是有若干字符组成的序列,C/C++中每个字符串都以'\0'作为结尾,这样就很容易找到字符串的最后尾部,但是需要一个额外字符的开销,容易造成越界;
- 常量字符串是在一块单独的只读的内存区域,其内容不可更改;
替换空格(剑指offer---面试题4)
题目:请实现一个函数,把字符串中的每个空格替换成“%20”。例如输入“We are happy.”,则输出“We%20are%20apy.”。
- void ReplaceBlank(char string[], int length);
解题思路:
(1)遍历字符串,统计出空格的总数numberOfBank;
(2)计算出替换之后的字符串长度,即newLength = originLength + 2 * numberOfBank;
(3)两个指针P1和P2分别指向原始的字符串的末尾和替换后的字符串的末尾,并且从后前遍历依次copy;
字符串的排列(剑指offer---面试题28)
题目:输入一个字符串,打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a、b、c所能排列出来的所有字符串abc、acb、bac、bca、cab和cba;
- void Permutation(char *str);
解题思路:
把字符串看成由两部分组成即第一个字符和后面的所有字符,第一步把第一个字符和后面的所有字符交换,即求出了所有可能出现在第一个位置的字符,第二步固定第一个字符,求后面所有字符的排列;
(1)初始化pBegin = str,然后调用PermutationRecursively(str, pBegin);
(2)for循环交换第一个字符和后面每个字符的顺序;
(3)递归调用PermutationRecursively(str, pBgein+1),即求后面所有字符的排列;
(4)回退交换第一个字符和后面每个字符的顺序;
第一个只出现一次的字符(剑指offer---面试题35)
题目:在字符串中找出第一个只出现一次的字符。例如输入"abaccdeff",则输出'b';
- char FirstNotRepeatingChar(char *str);
方法一:从头开始扫描字符串中的每个字符,并拿这个字符和后面的每个字符相比较,若后面没有重复的字符,则该字符是第一个只出现一次的字符;
缺点:时间复杂度O(n^2);
解题思路:数组实现哈希表;
(1)构建长度256的数组array作为哈希表,存储对应字符出现的次数;
(2)第一次扫描整个字符串,同时在哈希表更新每个字符出现的次数;
(3)第二次扫描整个字符串,同时查询哈希表若该字符出现的次数==1,则返回该字符即可;
翻转单词顺序 VS 左旋转字符串(剑指offer---面试题42)
题目一:输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。为简单起见,标点符号和普通字母一样处理。例如输入字符串"I am a student.",则输出"student. a am I";
- char *ReverseSentence(char *pData);
解题思路:
(1)先翻转整个句子,即Reverse(pBegin, pEnd);
(2)遍历整个句子,根据空格分隔符找到句子中的每一个单词并记录pBegin和pEnd,然后调用Reverse(pBegin, pEnd)翻转每一个单词;
题目二:字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转的功能。比如输入字符串"abcdefg"和数字2,该函数将返回左旋转2位得到的结果"cdefgab";
- char *LeftRotateString(char *str, int n);
解题思路:
(1)把字符串分成两部分,前部分长度为n,后部分长度为length-n;
(2)先翻转前部分、再翻转后部分、最后翻转整个字符串;
把字符串转换为整数(剑指offer---面试题49)
题目:实现atoi函数,即把字符串转换我整数;
- int atoi(const char *str);
解题思路:考虑边界条件空指针NULL、空字符串""、正负号、溢出、其他非数字的字符;
(1)初始化gStatus = false来判断是否非法输入,先判断空指针NULL和空字符串"";
(2)判断第一个符号是否为正负号,以及整个字符串是否只有一个符号;
(3)依次遍历整个字符串的每个字符ch,若ch是0~9数字则计算数值num大小(设置num为long型来判断是否溢出),只有顺利遍历完成后才设置gStatus = true;
(4)若ch不是0~9数字则设置num = 0并退出while循环;
正则表达式匹配(剑指offer---面试题53)
题目:请实现一个函数用来匹配包含'.'和'*'的正则表达式,模式中的'.'表示任意一个字符,而'*'表示它前面的字符出现任意次(包括0次)。在本题中,匹配是指字符串的所有字符匹配整个模式。例如字符串"aaa"与模式"a.a"和"ab*ac*a"匹配,但与"aa.a"及"ab*a"均不匹配;
- bool Match(char *str, char *pattern);
解题思路:pattern下一个字符是'*'时,pattern要么向后移动两个字符即匹配0个,要么保持不变即匹配>=1个;
(1)调用MatchCore(str, pattern);
(2)若str和pattern同时到达末尾即'\0',则返回true;
(3)若pattern先到达末尾,则返回true;
(4)若pattern下一个字符是'*'时,判断str和pattern的当前字符是否相同(或者判断pattern当前字符是否为'.'),若相同pattern向后移动两个字符('*'匹配0个)或者保持不变('*'匹配>=1个);若不相同pattern向后移动两个字符('*'匹配0个);
(5)若str和pattern的当前字符是否相同(或者判断pattern当前字符是否为'.'),若相同则匹配下一个字符,否则返回false;
表示数值的字符串(剑指offer---面试题54)
题目:请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如字符串"+100"、"-5e2"、"-123"、"3.1416"、"-1E-16"都表示数值,但"12e"、"1a3.14"、"1.2.3"、"+-5"、"12e+5.4"都不是数值;
- bool IsNumber(char *str);
解题思路:[sign] digit [.[digit]] [e|E [sign] digit];
(1)先判断指针str非空NULL,再判断'+'和'-'以及空字符串''';
(2)扫描数字直到遇到非数字为止;
(3)判断'.',若是则扫描数字,再判断'e'和'E',若是则判断e/E后面的数字部分是否有效;判断'e'和'E',若是则判断e/E后面的数字部分是否有效;否则返回false;
判断e/E后面数值是否有效:先是e/E、再可能+/-、最后是0~9;
字符流中第一个不重复的字符(剑指offer---面试题55)
题目:请实现一个函数用来找出字符流中第一个只出现一次的字符。例如,当从字符流中读出前两个字符"go"时,第一个出现一次的字符是'g';当从该字符流中读取前六个字符"google"时,第一个出现一次的字符是'l';
1 class CharStatistics 2 { 3 public: 4 CharStatistics():index(0); 5 void Insert(char ch); 6 char FirstAppearingOnce(); 7 8 private: 9 int occurrence[256]; 10 int index; 11 }
解决思路:类似面试题35,但是字符流是动态的,而且没有存储字符串,所以没法遍历整个字符串;
(1)初始化index = 0、occurrence[i] = -1;
(2)插入字符即Insert(ch)时,更新occurrence的值(-2表示重复、-1表示初始值、其他值表示在字符流中的索引,数组下标表示插入的字符),index++;
(3)查找第一个不重复的字符即FirstAppearingOnce()时,遍历整个数组occurrence,找到最小的>=0的值相对应的字符;