引入
在leetcode上做的一道题,对其中一个解法有个小坑,可以讨论下
面试题 10.02. 变位词组
先放代码
class Solution {
public:
vector<vector<string>> groupAnagrams(vector<string>& strs) {
map<string, int> mp;
vector<vector<string>> ans;
mp.clear();
ans.clear();
int i = 0;
for(string &str : strs) {
string status(26, 0);
for(char ch : str) {
status[ch - 'a']++;
}
if(mp.find(status) != mp.end()) {
ans[mp[status]].push_back(str);
} else {
mp[status] = i++;
vector<string> v{str};
ans.push_back(v);
}
}
return ans;
}
};
这个解法的关键在于如何存每个字符的在一个字符串中出现的次数,并将出现次数的情况当作map的key来使用,当然,我们可以选择用一个大小为26的int数组来存每个字符的次数,但每个字符串的情况不好当作map的key来存(虽然可以对次数做字符拼接,或者次数乘以质数的数学方法,但这里就不讨论了,我们主要讨论由此引出的对ASCII的讨论)
这里我们用了string来存,也就是一个string类型的变量status(26, 0),一个字符串中的每个元素是char类型的,对每个元素ch, 我们做status[ch - ‘a’]++操作,表示第ch-‘a’个字符处存的是字符ch在字符串中出现的次数。而这个次数其实是用char来存的,因为char在计算机中实际上是整数类型。
但这里我们忽略了一点,char在计算机中我们规定是一个字节,即8bit,表示的范围只有-128 ~ 127,所以当一个字符串中某个字符数超过127时,(由于补码的缘故)存在char中的值会变成负数,也就是在status[ch - ‘a’]++的过程中其所存的值只会是0 ~ 127,-128 ~ 0,0 ~ 127的循环,而不是我们预期的129,156 这样可能的实际出现的次数。
结论
ASCII的范围是0 ~ 127,char的范围是-128 ~ 127,好像没啥大关系,都在一个字节范围内。
而ASCII其实是一种很早就被编码到计算机里的一套字符编码规则,也就是编码表,仅有128个对应关系,即当整数在[0, 127]这个范围内时,可以通过内置在计算机中的编码方式,将整数映射成ASCII中的字符,如65在ASCII表中对应A,则以%c的规格打印65时,输出的就是65.
另外,随着中文等其他语言引入计算机,也就多出了后面许多的编码规则如GB2312(中国)、Shift_JIS(日本)、Unicode字符集(大集合)、UTF-8(可变长编码)等字符集编入计算机中,当我们选择某一规则显示当前文本时,编辑器就会以对应的规则去解释每个字符的表示,各字符集会有兼容和不兼容的缘故,因此会有部分乱码或者全篇乱码的现象。
顺手贴个表吧:
这种入门级的计算机知识,竟然以这种方式让我重拾一番,汗颜~