第一个只出现一次的字符

 处理字符串中重复或者次数出现等问题,最经常使用的就是哈希表,用字符串中的字符做为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 '#';
    }
}
相关文章
相关标签/搜索