请实现一个函数用来找出字符流中第一个只出现一次的字符。例如,当从字符流中只读出前两个字符 "go" 时,第一个只出现一次的字符是 "g"。当从该字符流中读出前六个字符“google" 时,第一个只出现一次的字符是 "l"。java
import java.util.LinkedList; public class Solution { //英文字符不会逃出128个ascii码的范围,因此定义这个长度的数组 //第一个ASCII码是一个空字符,因此我都是相对于` `进行一一排列 //好比数字'0'是30,那'0'-''等于30,就存在tmp[30]这个地方便可 //注意,tmp存的是出现的子树,即'0'出现了两次,那么tmp[30]就是2 int[] tmp = new int[128]; //维护一个队列,只保存一次进来的元素,重复的丢掉 LinkedList<Character> queue = new LinkedList<>(); //Insert one char from stringstream public void Insert(char ch) { //第一次进来的元素放进队列尾部 if(tmp[ch-' '] == 0){ queue.add(ch); } //进来一次,就对相应坐标加一,统计出出现次数 tmp[ch-' ']++; } //return the first appearence once char in current stringstream public char FirstAppearingOnce() { //取得时候是从队列得头部取,由于头部是比较早的数据 //出现次数大于等于2的话就不断丢弃,知道找到第一个出现次数为1的字符跳出循环 while(!queue.isEmpty() && tmp[queue.getFirst()-' ']>=2){ queue.removeFirst(); } //拿到这个第一个只出现一次的字符 if(!queue.isEmpty()){ return queue.getFirst(); } //拿不到了,说明没有只出现一次的字符,那么就返回# return '#'; } }
private int[] cnts = new int[256]; private Queue<Character> queue = new LinkedList<>(); public void Insert(char ch) { cnts[ch]++; queue.add(ch); while (!queue.isEmpty() && cnts[queue.peek()] > 1) queue.poll(); } public char FirstAppearingOnce() { return queue.isEmpty() ? '#' : queue.peek(); }