剑指Offer书籍上面的一道面试题,原题主要考察时间效率和空间效率,在字符串中找出第一个只出现一次的的字符,如输入“abaccdeff”,则输出b,我们第一时间想到的就是遍历字符串,从前往后,把遍历到的每一个字符与其他字符进行比较,如果在没有重复的字符,则该字符就是只出现一次的字符,当然这样完成的时间复杂度是0(n^2),这种方式我也完成了,代码如下:
//循环扫描字符串,找出第一次出现且仅出现一次的字符
char FirstNotRepeattingCharON2(char* pString)
{
if(pString == NULL)
return '\0';
if(strlen(pString) == 1)
return *pString;
for(int i = 0;i < strlen(pString);i++)
{
for (int j = 0;j < strlen(pString) ;j++)
{
if ((i == j) && (i == strlen(pString) - 1))
return pString[i];
if (j == i)
continue;
if (pString[i] == pString[j])
break;
if(j == strlen(pString) - 1)
return pString[i];
else
return '\0';
}
}
}
当然,上面的方法还达不到面试官的要求,因此,寻求改进的方法,考虑到时间复杂度的问题,实现每个字符出现的次数,可以考虑用hash来完成,定义hash表的键值(Key)是字符,而值(Value)是该字符出现的次数,没扫描到一个字符就在hash表的对应项中加1,字符(char)是一个长度为8的数据类型,因此总共有256种可能。下面是剑指Offer实现的代码:
//计算第一次出现且仅出现一次的字符
//时间复杂度o(n^2)
char FirstNotRepeattingChar(char* pString)
{
if (pString == NULL)
return '\0';
const int tableSize = 256;
unsigned int hashTable[tableSize];
for(unsigned int i = 0; i < tableSize;i++)
hashTable[i] = 0;
char* pHashKey = pString;
while (*(pHashKey) != '\0')
hashTable[*(pHashKey++)] ++;
pHashKey = pString;
while(*pHashKey != '\0')
{
if (hashTable[*pHashKey] == 1)
return *pHashKey;
pHashKey++;
}
return '\0';
}
通过这种方式时间复杂度变为了O(n^2)。