题目
Given a string, find the first non-repeating character in it and return it’s index. If it doesn’t exist, return -1.
Note: You may assume the string contain only lowercase letters.
思路1
可以建立一个哈希表,保存每一个字符的出现的位置,重复出现的字符可以用一个特殊的值,比如INT_MAX来表示。最后历遍整个表查找最小的值,也就是从未重复出现过的最靠前的字符位置。
class Solution {
public:
int firstUniqChar(string s) {
unordered_map<char,int> strmap;
for(int i=0;i<s.size();i++){
char now=s[i];
if(strmap.find(now)!=strmap.end()){
strmap[now]=INT_MAX;
}else{
strmap[now]=i;
}
}
int min=INT_MAX;
for(unordered_map<char,int>::iterator iter=strmap.begin();iter!=strmap.end();iter++){
min=min>=(iter->second)?(iter->second):min;
}
return min==INT_MAX?-1:min;
}
};
执行时间79ms,不是很理想。
思路2
哈希表更适合记录一些离散的值,比如数字,然而note指出,字符串中出现的只会是小写字母,那么完全可以建立一个数组来记录位置。
所以可以把哈希表改为数组,这样时间减少到了42ms,毕竟哈希表的访问速度比数组慢不少。
class Solution {
public:
int firstUniqChar(string s) {
int pos[26];
//初始化数组
for(int i=0;i<26;i++){
pos[i]=-1;
}
//更新数组,使得每一个没有重复出现的字符保持着出现的位置
for(int i=0;i<s.size();i++){
int now=s[i]-'a';
pos[now]=pos[now]<0?i:INT_MAX;
}
int min=INT_MAX;
//查询数组,寻找最小值,即最早出现的位置
for(int i=0;i<s.size();i++){
int now=s[i]-'a';
if(pos[now]>=0&&pos[now]<min){
min=pos[now];
}
}
return min==INT_MAX?-1:min;
}
};
这个解法带来的问题就是,需要用一个额外的值来记录从未出现过的字符,使得最后查询的时候变得麻烦了一些。
另外,最后查询的时候其实并不需要历遍整个字符串,只需要记录第一个出现的非INT_MAX(没有重复出现),非-1(在字符串中出现过)的位置即可。
思路三
前面两个思路记录的是位置信息,然而最后查询历遍的时候发现位置信息完全可以被变量 i 所取代,所以记录的信息实际上是是否出现过以及是否重复 两点而已。那么换一个思路,记录每个字符出现的次数,可以将这两点合并为出现次数是否为1
class Solution {
public:
int firstUniqChar(string s) {
int times[26]={};
int size=s.size();
for(int i=0;i<size;i++){
times[s[i]-'a']++;
}
for(int i=0;i<size;i++){
int now = s[i]-'a';
if(times[now]==1){
return i;
}
}
return -1;
}
};
执行时间依然是42ms,但是代码简洁了不少。
思路4
其实这并不是新的思路,但是前面代码写错了,思路2中既然记录了位置,为什么还要历遍字符串呢,历遍一遍记录位置的数组取最小值就好了。
class Solution {
public:
int firstUniqChar(string s) {
int pos[26];
//初始化数组
for(int i=0;i<26;i++){
pos[i]=-1;
}
//更新数组,使得每一个没有重复出现的字符保持着出现的位置
for(int i=0;i<s.size();i++){
int now=s[i]-'a';
pos[now]=pos[now]<0?i:INT_MAX;
}
int min=INT_MAX;
//查询数组,寻找最小值,即最早出现的位置
for(int i=0;i<26;i++){
if(pos[i]>=0&&pos[i]<min){
min=pos[i];
}
}
return min==INT_MAX?-1:min;
}
};
执行时间39ms,果然比思路3快一点。
思路5
待续