第一个只出现一次的字符相关问题

来源:互联网 发布:高松好玩吗 知乎 编辑:程序博客网 时间:2024/06/05 16:38

一 第一个只出现一次的字符

一开始的思路就是书中,遍历到每一个字符,然后与之后的字符做对比,知道符合要求的字符出现。显然这种方法效率底下,如果字符串有n个字符,每个字符与之后的字符做对比,这种方法的时间复杂度为On2)。

反复思考也没想出其他方法,书中提出建立简单哈希表,用以统计字符出现的次数,由于字符char为一个长度为8的数据类型,总共256种可能,于是创建长度为256的数组。每个字符用其ASCII码值作为数组的下标,对应数组值即为该字符出现次数。第一次扫描统计字符出现次数,第二次扫描即可得到第一个第一次出现的字符。

第一次扫描更新一个字符出现次数的时间是O(1),若有n个字符,则时间复杂度为On),第二次扫描,O1)就可以读出一字符的出现次数,故时间复杂度仍为On)。总复杂度为On)。要用一个长度为256的数组,空间复杂度为O(1)

实现代码如下

char FirstNotRepeatingChar(char* str){if (str == NULL)return'\0'; const int tablesize = 256;unsigned int hashTable[tablesize];for (unsigned int i = 0; i < tablesize;i++){hashTable[i] = 0;}char* HashKey = str;while (*(HashKey)!='\0'){hashTable[*(HashKey++)]++;}HashKey = str;while (*HashKey!='\0'){if (hashTable[*HashKey] == 1)return *HashKey;HashKey++;}return '\0';}

二 删除字符串1中在字符串2出现的字符 

同样借鉴上述方法,采用一个新字符串存储符合要求的字符,首先扫描字符串2,然后扫描字符串1,如果该字符出现次数为0,则将其添加到新字符串中。实现代码如下。


void str1Substr2(string str1,string str2){string ans = "";bool hash[256];memset(hash,0,sizeof(hash));for (int i = 0; i < str2.size();i++){hash[str2[i]] = 1;}for (int j = 0; j < str1.size();j++){if (!hash[str1[j]])ans += str1[j];}cout << ans<<endl;}

三 删除字符串中的重复字符

延用上述思路,只不过将数组设置为bool型,先将其设置为false,然后扫描逐个字符串,首先将出现的字符添加至新字符串中,然后将对应值设置为true,一次实现字符的重复出现。实现代码如下


void deletedouble(string str){const int size = 256;bool hashTable[size];memset(hashTable,0,sizeof(hashTable));string sp="";for (int i = 0; i < str.size();i++){if (hashTable[str[i]] == false){sp += str[i];hashTable[str[i]] = true;}}cout << sp;}

四  变位词的检验

   首先创建一用数组是西安的简单哈希表,来统计字符串中每个字符出现的次数,当扫描到第一个字符串中的字符时为哈希表对应项的值增加1.接下来扫描第二个字符串,扫描每个字符时为对应项的值减去1,。如果扫描完第二个字符后,哈希表中的所有值都为0,则为变位词。实现代码如下


bool isAnagram(char* str1,char* str2){const int size = 256;unsigned int hashTable[size];memset(hashTable,0,sizeof(hashTable));char* p1 = str1;while (*p1 != '\0'){hashTable[*p1]++;p1++;}p1 = str2;while (*p1!='\0'){hashTable[*p1]--;p1++;}for (int i = 0; i < size; i++){if (hashTable[i] != 0)return false;}return true;}


0 0