在一个字符串(0<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置, 如果没有则返回 -1(需要区分大小写).
思路1、两个for循环,没到i位置另一个循环从i+1开始遍历,如果存在相同的则,使用一个visited数组记录后面的位置已经被问过,下次不再访问。
class Solution {
public:
int FirstNotRepeatingChar(string str) {
int res = -1;
vector<bool> visited(str.size(),false);
for(int i = 0;i<str.size();++i){
bool flag = 1;
if(visited[i]==false){
visited[i]=true;
for(int j = i+1;j<str.size();++j){
if(str[i]==str[j]){
visited[j] = true;
flag = 0;
}
}
if(1==flag){
res = i;
break;
}
}
}
return res;
}
};
方法2:使用hash结构,空间换时间
思路:先统计出现次数,然后再遍历字符串找到出现次数为1的即可
class Solution {
public:
int FirstNotRepeatingChar(string str) {
int res = -1;
unordered_map<char,int> str_hash;//使用哈希数据结构
for(int i = 0;i<str.size();++i){//先统计出现次数
if(str_hash.find(str[i])==str_hash.end())
str_hash[str[i]]=1;
else
str_hash[str[i]]++;
}
//然后再遍历一次,找到出现次数为1的返回下标
for(int i = 0;i<str.size();++i){
if(str_hash[str[i]]==1){
res = i;
break;
}
}
return res;
}
};
思考:方法2中使用了unordered_map的结构,但是哈希表在创建的时候比较费时,红黑树创建时间复杂度为O(n*logn),而哈希表创建时间复杂度也不低,那么能不能简化该结构?自己创建一个哈希?
下面使用vector<int>创建一个大小为128的数组,ASCII中字符范围为0-127,所以可以兼容所有的字符,第一次遍历统计字符出现的次数,第二次遍历寻找次数是否为1,查找时间复杂度为O(1)
class Solution {
private:
int process(string str) {
if (str.size() == 0)
return -1;
vector<int> arr = vector<int>(128,0);//哈希思想,创建一个大小为128的数组,初始化为0
for (int i = 0; i < str.size(); ++i) {
arr[str[i]] += 1;//找到该字符对于的位置,值+1
}
for (int i = 0; i < str.size(); ++i) {
if (arr[str[i]] == 1) {//如果该位置的次数为1,直接返回即可
return i;
}
}
return -1;
}
public:
int FirstNotRepeatingChar(string str) {
if(str.size()==0)
return -1;
return process(str);
}
};