請實現一個函數用來找出字符流中第一個只出現一次的字符。例如,當從字符流中只讀出前兩個字符 "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(); }