第一种求解方法是:暴力求解,并分析时间复杂度和空间复杂度
扫描字符串,每次拿当前的一个字符与后面的字符进行比较,如果后面的字符没有出现该字符,则该字符是第一个只出现一次的字符;否则,扫描下一个字符。
假设字符长度为n,则时间复杂度是
O
(
n
2
)
O(n^2)
O(n2),空间复杂度是
O
(
n
)
O(n)
O(n).
有没有更小的时间复杂度方法?使用哈希表
第二种方法使用哈希表,并分析时间复杂度和空间复杂度。
使用哈希表也可以分为两种方法,第一种方法是首先统计每个字符在字符串中出现的次数,记为value,然后再次扫描字符串查看字符在哈希表中的值是否为1。
第二种方法是记录字符在字符串出现的位置,首先哈希表初始化为-1,遍历字符串,记录字符在字符串第一次出现的位置,如果该字符再次出现在字符串,则将该字符对应的哈希表的值(value)设为-2,最后找出哈希表中值最小的对应的键值即为字符串中第一个只出现一次的字符。
分析时间复杂度和空间复杂度,额外使用长度为256的数组作为哈希表,空间复杂度为
O
(
1
)
O(1)
O(1),第一次扫描时,在哈希表中更新一个字符出现的次数的时间是
O
(
1
)
O(1)
O(1),或者更新字符的位置的时间也是
O
(
1
)
O(1)
O(1),如果字符串长度为n,那么第一次扫描的时间复杂度为
O
(
n
)
O(n)
O(n)。第二次扫描时,同样在
O
(
1
)
O(1)
O(1)时间内能读出一个字符出现的次数或者字符出现的位置,时间复杂度是
O
(
n
)
O(n)
O(n)。总的时间复杂度是
O
(
n
)
O(n)
O(n)。
题目描述:
在一个字符串(0<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置, 如果没有则返回 -1(需要区分大小写).
使用第一种方法,哈希表记录字符在字符串中出现的次数
int FirstNotRepeatingChar(string str) {
int strSize=str.size();
//处理错误输入
if(strSize<=0) return -1;
//处理特殊输入
if(strSize==1) return 0;
vector<int> hashtable(256,0);
//哈希表存放字符出现的次数,遍历字符串
for(int i=0;i<=strSize;i++){
hashtable[str[i]]++;
}
//第二次遍历字符串,输出第一个出现一次的字符
for(int i=0;i!=strSize;i++){
if(hashtable[str[i]]==1)
return i;
}
return -1;
}
如果使用第二种方法,哈希表记录字符出现的位置。
int FirstNotRepeatingChar(string str){
//首先获取字符串的长度
int strSize=str.size();
//特殊情况处理
if(strSize<=0) return -1;
if(strSize==1) return 0;
//char是长度为8的数据类型,总共有256种可能
int tableSize=256;
int hashTable[tableSize];
//初始化哈希表
for(int i=0;i<tableSize;++i){
hashTable[i]=-1;
}
//第一次扫描字符串,如果字符为在字符串中出现过,则将对应的哈希表的值设为在字符串中的位置;否则将对应的
//哈希表的值设为-2
for(int i=0;i<strSize;++i){
if(hashTable[str[i]]==-1)
hashTable[str[i]]=i;
else if(hashTable[str[i]]>=0)
hashTable[str[i]]=-2;
}
//扫描哈希数组,找到最小的大于等于0的值对应的字符就是第一个只出现一次的字符,这个值就是它在字符串中的位置
int min=strSize;
for(int i=0;i<tableSize;++i){
if(hashTable[i]>=0 && hashTable[i]<min)
min=hashTable[i];
}
if(min==strSize) return -1;
else return min;
}