1.1 实现一个算法,确定一个字符串的所有字符是否全都不同。不允许使用额外的数据结构。
解答:这里假定字符集为ASCII码,可以与面试官沟通确认字符串使用的字符集。由于字符集是有限的,建立一个数组模拟的Hash表记录每个字符是否出现,线性扫描一次字符串即可,复杂度O(len(s)).如果字符集较大,需要考虑空间开销,则可以用bitset来实现。
1 bool isUnique(string s) { 2 bool record[256]; 3 memset(record, 0, sizeof(record)); 4 size_t size = s.size(); 5 for(size_t i = 0; i < size; ++i) { 6 if (record[s[i]] == true) 7 return false; 8 else 9 record[s[i]] = false; 10 } 11 return true; 12 }
可以加一个剪枝:如果字符串的大小大于字符集的大小了,那么该字符串肯定是存在重复字符的。
1 bool isUnique(string s) { 2 size_t size = s.size(); 3 if (size > 256) 4 return false; 5 bool record[256]; 6 memset(record, 0, sizeof(record)); 7 for(size_t i = 0; i < size; ++i) { 8 if (record[s[i]] == true) 9 return false; 10 else 11 record[s[i]] = false; 12 } 13 return true; 14 }
补充:假设对空间开销非常严苛,可以考虑先对字符串中的字符排序,然后进行一次线性扫描;如果还不允许改变字符串原有的内容,那么就只能暴力搜查了吧。
1.2 用C或C++实现void reverse(char * str)函数,即反转一个‘ ’结尾的字符串。
解答:
1 void reverse(char *str) { 2 if (str == nullptr) return; 3 size_t length = strlen(str); 4 for (size_t i = 0; i < length / 2; ++i) { 5 // swap str[i] and str[length - 1 - i]; 6 char temp = str[i]; 7 str[i] = str[length - 1 - i]; 8 str[length - 1 - i] = temp; 9 } 10 }
1.3 给定两个字符串,请写程序,确定其中一个字符串的重新排列后,能否变成另一个字符串。
解答:这里同样假定字符集是ASCII码,假定判断字符串相等时,大小写是区分的。在开始时通过检查两个字符串长度是否相等进行剪枝,然后,用一个数组记录第一个字符串中每个字符出现的次数,然后判断第二个字符串中每个字符出现的次数是否与第一个字符串相等即可。
1 bool canConvert(string s1, string s2) { 2 if (s1.size() != s2.size()) 3 return false; 4 int record[256]; 5 memset(record, 0, sizeof(record)); 6 for (auto &c : s1) { 7 ++record[c]; 8 } 9 for (auto &c : s2) { 10 if (--record[c] < 0) 11 return false; 12 } 13 return true; 14 }
1.4 编写一个方法,将字符串中的空格全部替换为"%20".假定字符串尾部有足够的空间存放新增字符,并且知道字符串的真实长度。示例:
输入: "Mr John Smith"
输出: "Mr%20John%20Smith"
解答:需要改变字符串长度的问题,通常从尾部开始处理比较高效,因为可以避免字符的重复移动。
1 void replaceSpace(char str[], int length) { 2 //length为字符串实际长度,不包括结尾的' ' 3 if(length <= 0) return; 4 int space_cnt = 0; 5 for (int i = 0; i < length; ++i) { 6 if (str[i] == ' ') { 7 ++space_cnt; 8 } 9 } 10 if (space_cnt > 0) { 11 int j = length + space_cnt * 2; 12 str[j] = '