第一个只出现一次的字符
题目:在一个字符串中找到第一个只出现一次的字符。如输入abaccdeff,则输出b。
由于题目与字符出现的次数相关,我们可以统计每个字符在该字符串中出现的次数。要达到这个目的,我们需要一个数据容器来存放每个字符的出现次数。在这个数据容器中可以根据字符来查找它出现的次数,也就是说这个容器的作用 是把一个字符映射成一个数字。在常用的数据容器中,哈希表正是这个用途。哈希表是一种比较复杂的数据结构。由于比较复杂,STL中没有实现哈希表,因此需要我们自己实现一个。
由于字符(char)是一个长度为8的数据类型,因此总共有可能256 种可能。首先申请一个长度为256的表,对每个字符进行hash计数即可。因为C/C++中有3种char类型:char,signed char,unsigned char。在对字符进行hash时,应该先将字符转为无符号类型;否则将下标出现负值时就会出现越界访问。
我们第一遍扫描这个数组时,每碰到一个字符,在哈希表中找到对应的项并把出现的次数增加一次。这样在进行第二次扫描时,就能直接从哈希表中得到每个字符出现的次数了。
使用指针代码如下:
1 char get(char *pString) 2 { 3 // 考虑全面 4 if(!pString) 5 return 0; 6 const int size = 256; 7 unsigned int hash[size]; 8 9 for(int i=0;i<256;i++) 10 hash[i]=0; 11 12 char *hashKey = pString; 13 14 while((*hashKey)!='\0') 15 { 16 // 转为unsigned char型,防止下标出现负数 17 ++hash[(unsigned char)*(hashKey++)]; 18 } 19 hashKey = pString; 20 while((*hashKey)!='\0') 21 { 22 if(hash[(unsigned char)*hashKey]==1) 23 return *hashKey; 24 hashKey++; 25 } 26 27 return 0; 28 }
使用数组如下:
1 int main () 2 { 3 string s; 4 cin>>s; 5 int count[256]={0}; 6 for(int i=0;i<s.size();++i) 7 ++count[(unsigned char)s[i]]; 8 for(int i=0;i<s.size();++i) 9 { 10 if(count[(unsigned char)s[i]]==1) 11 { 12 cout<<s[i]<<endl; 13 break; 14 } 15 } 16 return 0; 17 }
总结:如果需要判断多个字符是不是在某个字符串里出现过或者统计多个字符在某个字符串中出现的次数,我们可以考虑基于数组创建一个简单的哈希表。这样可以用很小的空间消耗换来时间效率的提升。