處理字符串中重複或者次數出現等問題,最經常使用的就是哈希表,用字符串中的字符做爲key,字符出現次數做爲value,假定只有ASCII碼範圍內的字符,則能夠開闢一個256大小的int數組,將每一個字符(key)映射到該數組的對應位置上,計算每次出現的次數便可,遍歷一次字符串,計算每一個字符出現的次數,保存在int數組的對應位置上,第二次遍歷字符串,若第一次出現某個字符對對應到的哈希表的對應位置處的元素爲1,則該字符即是第一個只出現一次的字符,若是咱們是遍歷哈希表(int數組),則找到的哈希表中的第一個元素爲1的位置對應的字符爲字符串中第一個最小的只出現一次的字符。時間複雜度爲O(n),須要額外的256個int空間來輔助,能夠看作空間複雜度爲O(1)。java
另外,若是要省空間,咱們能夠bitmap算法,用兩個位來表示對應字符出現的次數,出現0次,則爲00,出現一次則爲01,出現2次及以上,都維持在10便可。算法
另外,有一點須要注意,char的範圍在-128-127,unsigned char的範圍纔是在0-255,所以ASCII值在128-255之間的字符,若是保存爲了char型,其轉化爲int值的範圍是在-128--1之間,這點在下面的代碼中有體現。數組
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 '#'; } }