字符流中第一個不重複的字符

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