看完题目后,我的第一反应就是应该用Hash表做,看了一眼讨论区都是用的Hash表,心里就有底了。
然后进一步理清了思路:
字符为key,出现次数为value,第一次遍历一遍字符串,把所有字符和对应的出现次数存入哈希表;
第二次顺序遍历字符串,对每一个字符查询出现次数,第一个次数为1的就返回。
代码如下:(这是为数不多的一次思路和代码实现都没有看书和别人的代码的)
ps:代码有漏洞,没有处理所有字符都出现不止一次的情况。
在第二次循环结束前加上:if ( i == str.size()-1 ) result=-1;
class Solution {
public:
int FirstNotRepeatingChar(string str) {
if (str=="") return -1;
//将字符串遍历存入哈希表中
std::unordered_map<char, int> map;
//std::unordered_map<char, int>::iterator it;
for(int i=0; i<str.size(); i++){
if(map.find(str[i]) != map.end()){
int temp = map[str[i]];
map[str[i]] = ++temp;
}
else{
//map(str[i]) = 1;
map.insert(std::make_pair(str[i], 1));
}
}
int result;
for(int i=0; i<str.size(); i++){
if(map[str[i]] == 1){
result = i;
break;
}
}
return result;
}
};
这道题本身花的时间并不多,写代码和debug大概一共15分钟。但是前期的大部分时间40-50分钟,都用在查STL中的String和哈希表调用方法了,这上面花费了不少时间。
C++的STL真的需要花时间好好的学一学了。
看过别人代码之后对之前代码的简化:
(可以看出之前代码写的繁琐的原因还是,对map用法的不熟悉)
class Solution {
public:
int FirstNotRepeatingChar(string str) {
if (str.empty())
return -1;
//将字符串遍历存入哈希表中
std::unordered_map<char, int> map;
//std::unordered_map<char, int>::iterator it; //可以不用map的迭代器
for(int i=0; i<str.size(); ++i){
//map[str[i]] = map[str[i]]+1; //另一种写法
++map[str[i]];
}
int result;
for(int i=0; i<str.size(); ++i){
if(map[str[i]] == 1){
result = i;
break;
}
if(i == str.size()-1) result=-1;
}
return result;
}
};
书上的方法:
由于只需要一个非常简单的哈希表就可以满足我们的要求,所以,可以自己用数组实现一个简单的哈希表。
代码如下:(其中对字符不需要强制类型转换成unsigned int型,可以直接用作数组的索引)
class Solution {
public:
int FirstNotRepeatingChar(string str) {
if (str.empty())
return -1;
const int HashTableSize = 256;
unsigned int HashTable[HashTableSize];
for (int i=0; i<HashTableSize; ++i){
HashTable[i] = 0;
}
//遍历字符串,向哈希表中对应位置存字符出现次数
for(int i=0; i<str.size(); i++){
++HashTable[str[i]];
}
//遍历字符串,找到第一个出现次数为1的字符位置
int posi;
for(int i=0; i<str.size(); i++){
if(HashTable[str[i]]==1)
{
posi = i;
break;
}
}
return posi;
}
};