找出字符串中第一个只出现一次的字符
输入描述:
输入一个非空字符串
输出描述:
输出第一个只出现一次的字符,如果不存在输出-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;
}