第一個只出現一次的字符

 處理字符串中重複或者次數出現等問題,最經常使用的就是哈希表,用字符串中的字符做爲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 '#';
    }
}
相關文章
相關標籤/搜索