每日一练(3) - 求一个字符串中第一次只出现一次的字符(3种解法)

题目描述

请实现一个函数用来找出字符流中第一个只出现一次的字符。例如,当从字符流中只读出前两个字符"go"时,第一个只出现一次的字符是"g"。当从该字符流中读出前六个字符“google"时,第一个只出现一次的字符是"l"。

思路

【注意】

  • 这里都要考虑到字符串为空的情况,如果为空,返回’\0’;
  • 如果字符串中不存在只出现一次的字符,也返回’\0’;

方法一 字符串扫描(笨方法)

第一种方法相对比较笨,但是也最容易被想到和实现。我们需要两个for循环来实现,外层循环从头开始遍历字符串,其指向的是当前要判断的字符的下标。内层循环从头开始遍历字符串,如果遇到和外层循环相同的字符并且它们的下标不同,那么该字符就不是出现一次的字符,外层循环++,继续判断下一个字符,这是内层循环又要从头开始扫描字符串。

   //查找第一个只出现一次的字符
         char findFirstChar(char *pString)
         {
             if(pString == "") return '\0';  //如果字符串为空,返回'\0';
             char *temp = pString;
             temp = pString;
             for(int i = 0; temp[i] != '\0'; i++)
             {
                 int j;
                 for(j = 0; temp[j] != '\0'; j++)
                 {
                     if(temp[i] == temp[j] && i != j) //如果遇到和外层循环相同的字符并且它们的下标不同,直接退出循环,继续判断下一个元素
                        break;
                 }
                 if(temp[j] == '\0') //如果内存循环已经扫描到字符串结尾,说明下标为i的元素只出现一次,可以直接返回
                 {
                     return pString[i];
                 }
             }
             return '\0'; //字符串中不存在只出现一次的字符,也返回'\0';
         }

【分析】上面的代码时间复杂度为O(n),性能很低,每判断一个字符,都需要从头开始扫描字符串
下面,让我介绍利用哈希表实现查找的方法

方法二 哈希表

我们可以定义哈希表的键值(Key)是字符的ASCII值,而值(Value)是该字符出现的次数【hashTable[‘s’] = 1 (s就是哈希表的键值,而1就是哈希表的value)】。同时我们需要扫描两次字符串,第一次扫描字符串时,每扫描到一个字符就在哈希表的对应项中把次数加1。接下来第二次扫描的时候,没扫描到一个字符就能在哈希表中得到该字符出现的次数。找出第一个Value为1的那个key就是我们需要找到那个字符

  		char findFirstChar2(char *pString)
         {
             //空字符串
          if(pString == "")
                return '\0';

          // 1、初始化
          /*
			   定义一个哈希表;为什么是256, 因为字符的ASCLL表表示256个字符;
			   我们是以字符的ASCLL值为数组下标,而字符的出现次数为数组内容的;
   		*/
          int hashTable[256];  //定义一个哈希表
          for( int i = 0; i < 256; ++ i)
                hashTable[i] = 0;

          //2、以字符作为数组下标,求每个字符出现的次数
          char* pHashKey = pString;
          while(*pHashKey != '\0')
          {
              hashTable[*pHashKey] ++;
              pHashKey++;
          }

          // 3、找到第一次出现一次的字符,就是在数组中第一次存储为1所对应的字符
          pHashKey = pString;
          while(*pHashKey != '\0')
          {
                if(hashTable[*pHashKey] == 1)
                      return *pHashKey;
                pHashKey++;
          }
          return '\0';
         }

【分析】哈希表对于查找时十分方便,当我们遇到查找问题时,可以优先考虑一下哈希表

方法三 map容器

其实用map和哈希表的实现原理类似,其都是通过将键与其值相映射

static char findFirstChar3(char *pString)
         {
             string str = ""; //用字符串保存读取的字符流,,方便后面求字符串大小
             map<char, int> hashTable;  //声明map实现哈希表,存放对应字符出现的个数( 字符:出现次数)
             int ch;
             while(*pString != '\0')
             {
                 str += *pString;
                 hashTable[*pString++]++;  // hashTable['c'] = 1;
             }
             for(int i = 0; i < str.size(); i++)
             {
                 if(hashTable[str[i]] == 1)
                 {
                     return str[i];
                 }
             }
             return '\0';
         }
  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值