题目描述
找出字符串中第一个只出现一次的字符
输入描述:
输入一个非空字符串
输出描述:
输出第一个只出现一次的字符,如果不存在输出-1
输入例子:
asdfasdfo
输出例子:
o
使用map记录字符出现的次数,使用vector记录只出现一次的元素及其次序,在删除重复的元素的同时保持先后次序,最终返回vector中剩余的第一个元素或者返回-1.
#include<iostream>
#include<map>
#include<vector>
using namespace std;
struct Record{
int count;//现出次数
int ind;//在vector中的下标
};
struct Link{
char c;
int isdel;//判断当前的元素是否已经“去除”
int pre,next;
};
int main(){
string s;
while(cin>>s){
map<char,Record> mcR;
vector<Link> vL;
Link Rtp;
int Rindex=0;
int Lindex=0;
int first=-1;//始终指向vector中的第一个元素,为-1表示vector为空
int last=-1;//始终指向vector中的最后一个元素,为-1表示vector为空
for(auto ceh:s){
mcR[ceh].count+=1;
if(mcR[ceh].count==1){
mcR[ceh].ind=Rindex++;//第一次出现时设置在Vector中的下标
//建立链接关系
Rtp.c=ceh;
Rtp.pre=last;//上一个标号
if(last!=-1)//设置上一个元素的下一个标号
vL[last].next=Lindex;
Rtp.next=-1;//当前元素是最后一个元素,下一个标号设置为-1
Rtp.isdel=0;
vL.push_back(Rtp);
last=Lindex;//新的last为当前的标号
if(first==-1) first=Lindex;
++Lindex;
}
else{
//“去除”元素,整理链接关系
int nowind=mcR[ceh].ind;
if(vL[nowind].isdel==0){
int preind=vL[nowind].pre;
int nextind=vL[nowind].next;
if(preind>-1) vL[preind].next=nextind;
if(preind==-1) first=nextind;
if(nextind!=-1 && nextind<Lindex) vL[nextind].pre=preind;//别忘记判断nextind!=-1
if(nextind==-1) last=preind;
vL[nowind].isdel=1;
}
}
}
if(first==-1)
cout<<-1<<endl;
else
cout<<vL[first].c<<endl;
}
return 0;
}
下面是常规解法,需要遍历两次,第一次遍历全部输入字符,第二次遍历去重后保持次序的字符。
#include<iostream>
#include<map>
#include<vector>
using namespace std;
int main(){
string s;
while(cin>>s){
map<char,int> mci;
vector<char> vc;
for(auto ceh:s){
mci[ceh]+=1;
if(mci[ceh]==1){
vc.push_back(ceh);
}
}
int isfind=0;
for(auto ceh:vc){
if(mci[ceh]==1){
isfind=1;
cout<<ceh<<endl;
break;
}
}
if(isfind==0)
cout<<-1<<endl;
}
return 0;
}