描述

请实现一个函数用来找出字符流中第一个只出现一次的字符。例如,当从字符流中只读出前两个字符"go"时,第一个只出现一次的字符是"g"。当从该字符流中读出前六个字符“google"时,第一个只出现一次的字符是"l"。
后台会用以下方式调用Insert 和 FirstAppearingOnce 函数
string caseout = "";
1.读入测试用例字符串casein
2.如果对应语言有Init()函数的话,执行Init() 函数
3.循环遍历字符串里的每一个字符ch {
Insert(ch);
caseout += FirstAppearingOnce()
}
2. 输出caseout,进行比较。

返回值描述:

如果当前字符流没有存在出现一次的字符,返回#字符。


示例1

输入:
"google"
返回值:
"ggg#ll"


题目简述

        在集合中不断加入字符,对于新的集合,找到第一个只出现过一次的字符,若没有则返回 # 。

算法一: 哈希表+字符串

时间复杂度:O(N)

思路:

        每个字符都有与之对应的ASCII码,可直接与数组下标对应,我们用数组a统计每个字符出现的次数。
        Insert():每次插入一个元素都将它加入字符串中,然后将a数组加 1 。
        FirstAppearingOnce():从 t 开始遍历字符串,找到第一个只出现过一次的字符 , 用 t 标记下这个位置,并返回它的字符串 。

代码:

class Solution
{
public:
  //Insert one char from stringstream
    int a[1000]={0};
    queue<char> q;
    string s;
    int t=0;
    void Insert(char ch) {
        s+=ch;
        a[ch]++;
    }
  //return the first appearence once char in current stringstream
    char FirstAppearingOnce() {
        for(int i=t;i<s.size();i++){
            if(a[s[i]]==1){
                t=i;
                return s[i];
            }
        }
        return '#';
    }
};


算法二:哈希表+队列

时间复杂度:O(N)

思路:

        每个字符都有与之对应的ASCII码,可直接与数组下标对应,我们用数组a统计每个字符出现的次数。
        Insert():用数组a记录字符出现的次数,将未出现过的字符加入队列中,然后不断判断队首字符,是否出现过多次,若有多次则弹出队首字符,否则停止,这样保证了队首始终为只出现过一次的字符。
        FirstAppearingOnce():直接取队首元素即可,若队列为空,则返回#。

图解:

代码:

class Solution
{
public:
  //Insert one char from stringstream
    int a[1000]={0};
    queue<char> q;
    int t=0;
    void Insert(char ch) {
        a[ch]++;//统计元素出现的次数
        if(a[ch]==1) q.push(ch); 
        while(!q.empty()){ //弹出出现多次的字符,保证队首始终是只出现过一次的字符
            if(a[q.front()]>1) q.pop(); 
            else break;
        }
    }
  //return the first appearence once char in current stringstream
    char FirstAppearingOnce() {
        if(!q.empty()){
            return q.front();
        }
        return '#';
    }
};