day04-刷题 找出字符串中第一个只出现一次的字符

找出字符串中第一个只出现一次的字符

输入描述:

输入一个非空字符串

输出描述:

输出第一个只出现一次的字符,如果不存在输出-1

示例1

输入

asdfasdfo

输出

o


思路,一般这种题指定用hashmap解决,把整个数组丢进一个hashtable中,以空间换时间,以追求最高效时间复杂度O(N),当然还有暴力两层遍历的O(N²),有时候 做之前就会被告知时间复杂度O(N²)的算法就别写了,(反正我遇到过),如果没说,你可以从蠢办法开始,步步深入;

所以

1.暴力求解O(n^2)

由于要求是发现第一个只出现一次的既不重复的字符,采用双层循环结构,内层循环遍历与外层循环遍历逐个比对是否有相同,有则排除继续遍历,直到发现没有重复的;

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void findSingle(char *str){
    int i,j;
    int len = strlen(str);
    for(i=0;i<len;i++){
        for(j=i+1;j<len;j++){
            if(str[i] == str[j]){
                break;
            }
            if(j == len - 1){
                printf("%c",str[i]);
                return ;
            }
        }
    }
}

int main(){
    char str[] = "abaccdeff";
    findSingle(str);
    return 0;
}

2.利用find()

  • 实际上时间复杂度依旧高,换汤不换药,只使用起来方便罢了
#include <iostream>
#include <string>
using namespace std;

int main(){
    string s;
    int flg = -1;
    while(getline(cin,s)){
        unsigned int i;
        for (i=0;i<s.size();i++){
            if(s.find(s[i])==s.find(s[i])){
                flg = true;
                cout<<s[i]<<endl;
                    break;
            }
        }
        if(i==s.size()){
            cout<< flg << endl;
        }
    }
    return 0;
}

3.利用Ascii编码

C/C++字符使用Ascii编码,一个字符占一个字节即可以表示2的8次方个数,那么C/C++字符可以表示的256个字符,因此可以用一个256的数组来保存各个字符出现的次数,当然256个字符的Ascii值是0-255之间的所有数,而且’\0’的Ascii值0,所以可以用数组的下标来表示记录的是哪一个字符的个数。然后再遍历一次字符串,找出第一个只出现一次的字符。

char FindFirstSingleChar(char str[]){
    if(str==NULL||str[0]=='\0') return '\0';//字符串为空或为空串时返回'\0'
    int count[256]={0};//令所有字符出现次数为0
    int n=0;
    while(str[n]!='\0'){
        count[str[n]]++;//该字符出现次数加1
        n++;
    }
    n=0;
    while(str[n]!='\0'){
        if(count[str[n]]==1){//找到第一个只出现一次的字符
            return str[n];
        }
        n++;
    }
    return '\0';//字符串中不存在只出现一次的字符时,返回'\0'
}

4.常见优化手段–用空间换时间–hashtable

即我们只遍历一次字符串,然后下来记录每个字符出现的次数。对于字符串来讲,一般采用哈希表,然后对哈希表进行查询即可。如果只针对字符串为小写字母形式,则简单的采用int hashtable[26] = {0};来做存储。但这种情景相对较少,不够通用;

void findSingle(char *arr){  
    int hashtable[26] = {0};  
    int i;  
    int len = strlen(str);
    for(i=0;i<len;i++)  
        hashtable[arr[i]-'a']++;  

    for(i=0;i<len;i++){  
        if(hashtable[arr[i]-'a'] == 1){  
            printf("%c\n",arr[i]);  
            break;  
        }  
    } 
    if(i >= len){  
      return -1;
    }  
}  
  • 同样如果不仅线制对小写字母,各类字符都有的情况直接采用int hashtable[256] = {0};更通用
#include<iostream>
#include<string>
using namespace std;
const int Tabsize = 256;
int hashtab[Tabsize];
int main(){
    string str;
    while(cin>>str){
        bool flg = false;
        for(int i=0;i<Tabsize;++i) {
            hashtab[i]=0;
        }
        for(int i=0;i<str.size();++i){
            hashtab[str[i]]++;
        }
        for(int i=0;!flg && i<str.size();++i){
            if(hashtab[str[i]] == 1){
                cout<<str[i]<<endl;
                flg = true;
                break;
            }
        }
        if(!flg)
            cout<<'-1'<<endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/ego_bai/article/details/80461304