二刷:
看到题目之后,倒是一下子就想到了数组hash。但是不知道这个“第一次“怎么处理。
看了书之后,书上是再次遍历字符。我在旁边写了一个思路是用两个hash表,一个记录出现次数,另一个第一次出现的位置。于是把它实现了:
class Solution {
public:
int FirstNotRepeatingChar(string str) {
int hash[58] = {0}; // 记录出现次数
int hash2[58]; // 记录第一次出现位置
memset(hash2, -1, sizeof(hash2));
int length = str.size();
for(int i=0; i<length; i++) {
if(hash[str[i]-'A'] == 0) {
hash2[str[i]-'A'] = i;
}
hash[str[i]-'A']++;
}
int result = -1;
for(int i=0; i<58; i++) {
if(hash[i] == 1) {
if(result == -1) {
result = hash2[i];
} else {
result = min(hash2[i], result);
}
}
}
return result;
}
};
预料之中,运行时间变短了,空间稍微加了一点。
这次第二次A出来,第一次的数组初始化有点问题,int hash2[58] = {-1}; 只能使第一个元素是-1,其它元素是0,所以用memset。但是memset也很容易出问题,实在不行就遍历吧。
第二,因为不熟练或者脑子不清晰导致 min(hash2[i], result)写成min(hash2[i], hash2[result]).
这两个问题是我在xcode中调试发现的,否则又要搞很久吧。
/*******************************************/
牛客网上的题目要求与书上的略有不同,如上。书上说的是char,char是8bit字符类型,共有256个,所以简易hash表长度是256。
class Solution {
public:
int FirstNotRepeatingChar(string str) {
int length = str.length();
int tableSize = 58;
int hashTable[tableSize];
for(int i=0; i<tableSize; i++) {
hashTable[i] = 0;
}
for(int i=0; i<length; i++) {
hashTable[str[i]-'A']++;
}
for(int i=0; i<length; i++) {
if(hashTable[str[i]-'A'] == 1) {
return i;
}
}
return -1;
}
};
这是我借着对一个半月前看过书的一点记忆加上一点小技巧写出的答案。不是很完美,但有如下思考:
1.哈希表用普通数组实现是这道题妙处。题目要求区分大小写,我去网上查了一下ASCII码表,大写字母和小写字母不相邻着,'A'在第65个,‘z‘在第122个,所以hash表长度为122-64 = 58,有一些冗余,但问题不大。 这样就可以用字母与‘A’的差作为索引(从0开始),出现的次数作为键值,构造出一个简单的哈希表。
2.我的思考是再来一个hash表记录对应字符的位置。书上的思路是再次遍历原字符串。