题目描述
请实现一个函数用来找出字符流中第一个只出现一次的字符。
例如,当从字符流中只读出前两个字符 go
时,第一个只出现一次的字符是 g
。
当从该字符流中读出前六个字符 google
时,第一个只出现一次的字符是 l
。
如果当前字符流没有存在出现一次的字符,返回 #
字符。
数据范围
字符流读入字符数量 [0,1000]。
样例
输入:"google" 输出:"ggg#ll" 解释:每当字符流读入一个字符,就进行一次判断并输出当前的第一个只出现一次的字符。
方法一:哈希表+队列 O(n)
插入操作:
将字符推入队列中,并且在哈希表中的数量加 1 。
如果哈希表中记录该字符数量已经大于 1 ,则进行循环判断,如果队头字符的数量大于 2 了,就将其从队列中移出。为什么是队头字符,是因为如果你加入的字符不是队头字符,不管你是第 1 次出现,还是第 n 次,只要队头字符数量不大于 1 ,输出的第一个字符就是队头,题目要求的是第一个只出现一次的字符。查询操作:
- 如果队列为空,返回
#
。 - 如果队列不为空,返回队头字符。
我们具体个例子,就拿题目的样例来看:
第一步: 将 g
加入队列,并且这只是第一个元素,还不存在出现重复的元素,故第一个只出现一次的字符就是 g
。
第二步: 将 o
加入队列,此时第一个只出现一次的字符仍然是 g
。
第三步: 将 o
加入队列,此时哈希表中 o
的计数已经大于 1
,但是队头的 g
仍然只出现一次,每次查询只会查询队头元素,所以暂时不用删除队列中的 o
。
第四步: 将 g
加入队列,此时 g
的计数大于 1
,故要删除队头元素 g
。
同时队列后面的元素计数都大于 1
,故都要删除。所以当前没有只出现一次的字符,故返回 #
第五步: 将 l
加入队列,此时 l
就是第一个只出现一次的字符。
第六步: 将 e
加入队列,此时 l
仍然是第一个只出现一次的字符。
class Solution { public: unordered_map<char, int> count; queue<char> q; //Insert one char from stringstream void insert(char ch) { q.push(ch); if (++count[ch] > 1) while (q.size() && count[q.front()] > 1) q.pop(); } //return the first appearence once char in current stringstream char firstAppearingOnce() { if (q.empty()) return '#'; return q.front(); } };
欢迎大家在评论区交流~