经典考题——无重复字符问题(查找字符串中第一个无重复字符)

题目描述:

寻求最佳的算法

 编写一个高效率函数来找出一个字符串中第一个无重复字符.例如:”total”中的o,”teeter”中的r.要求算法效率优于O(n2)。

分析:个人觉得,这个题目如果不强调效率就有点简单了吧,两层循环弄一下应该没问题了。但是另外一个角度,我觉得这个题目肯定是要遍历字符串的,所以算法效率最低应该就是O(n)吧,不知道是否是这样。

在笔试群硕的时候,由于时间关系,这个题我没有写代码,在只有5分钟的情况下,写了个思路。我当时写的是:

对字符串排序(用O(n)以下的方法,很多啦),然后遍历一次排序后的字符串。回来后,我发现我思路有问题,这样做如何是找所有的无重复字符倒是可以,但是要找到第一个,就没法了。

这个题目在网上看了一下,思路倒是不少,其中有个典型思路听起来很简单,很有效率,但是事实上太没效率了。思路是:遍历字符串,如果当前字符在字符串中从前往后数和从后往前数的下标是一个数(在java和c++中有类的方法可以找到下标),那么就说明无重复。一听这思路,很简洁啊,效率也不错吧,其实不是,这里调用的类的方法效率就很低了,这方法内部肯定要遍历字符串,效率没有提高。

下面的代码是我回来之后写的,思路大概是:统计每个字符串的个数到字母表数组中,并且统计对应的出现的下标到索引数组,然后再遍历字母表数组,根据个数判断是否是重复的,并到索引数组中查找对应的下标是不是最小的(最前面的),就可以得到是哪一个字符是第一个无重复的了。

  1. /* 
  2. 编写一个高效率函数来找出一个字符串中第一个无重复字符.例如:”total”中的o,”teeter”中的r. 
  3. 要求算法效率优于O(n2). 
  4. */  
  5. #include <iostream>  
  6. using namespace std;  
  7.   
  8. char findStr(const char* str)  
  9. {  
  10.     int len=strlen(str),count[26],index[26];  
  11.     char result,curr;  
  12.   
  13.     for(int j=0;j<26;j++)  
  14.     {  
  15.         count[j]=0;  
  16.         index[j]=0;  
  17.     }  
  18.   
  19.     bool exist=false;  
  20.   
  21.     for(int i=len;i>0;i--)  
  22.     {  
  23.         curr=str[i-1];  
  24.         count[curr-'a']++;  
  25.         index[curr-'a']=i-1;  
  26.     }  
  27.   
  28.     int minIndex=len+1;  
  29.     for(i=0;i<26;i++)  
  30.     {  
  31.         if(count[i]==1)  
  32.         {  
  33.             if(index[i]<minIndex)  
  34.             {  
  35.                 minIndex=index[i];  
  36.             }  
  37.         }  
  38.     }  
  39.   
  40.     return str[minIndex];  
  41. }  
  42.   
  43.   
  44. int main()  
  45. {  
  46.     const char* test="aac";  
  47.   
  48.     cout<<findStr(test)<<endl;  
  49.   
  50.     return 0;  
  51. }  

以下代码和上面代码思路类似,但是更巧妙一点,没有记录索引,效率也为O(n):

参考如下网页:http://www.360doc.com/content/06/1023/12/11192_237819.shtml

  1. /* 
  2. 编写一个高效率函数来找出一个字符串中第一个无重复字符.例如:”total”中的o,”teeter”中的r. 
  3. 要求算法效率优于O(n2). 
  4. */  
  5. #include <iostream>  
  6. using namespace std;  
  7.   
  8. char findStr(const char* str)  
  9. {  
  10.     int p[256];  
  11.   
  12.     int i,j;  
  13.     for(i=0;i<256;i++)  
  14.         p[i]=0;  
  15.   
  16.     i=0;  
  17.     while(str[i]!='/0')  
  18.     {  
  19.         p[str[i]]++;  
  20.         i++;  
  21.     }  
  22.   
  23.     for(i=0;str[i]!='/0';i++)  
  24.     {  
  25.         if(p[str[i]]==1)  
  26.         {  
  27.             return str[i];  
  28.         }  
  29.     }  
  30.   
  31.     return 0;  
  32. }  
  33.   
  34.   
  35. int main()  
  36. {  
  37.     const char* test="acacdcefe";  
  38.   
  39.     cout<<findStr(test)<<endl;  
  40.   
  41.     return 0;  
  42. }  

网上还有一些其他解法吧,甚至用到了哈希的,不管了,以上两个程序已经很不错了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值