【剑指offer】字符流中第一个不重复的字符--Java代码

题目描述
请实现一个函数用来找出字符流中第一个只出现一次的字符。例如,当从字符流中只读出前两个字符"go"时,第一个只出现一次的字符是"g"。当从该字符流中读出前六个字符“google"时,第一个只出现一次的字符是"l"。
返回值描述:
如果当前字符流没有存在出现一次的字符,返回#字符。

解析:本题最简单的思路就是采用Hashmap,大门时要注意的一点是,必须要用到LinkedHashMap,HashMap和LinkedHashMap的主要区别是LinkedHashMap存储的键值对是有一定顺序的,先存入的键值会先访问。for(char ch:map.keySet())

import java.util.*;
public class Solution {
    //Insert one char from stringstream
    HashMap<Character,Integer> map=new LinkedHashMap<>();
    public void Insert(char ch)
    {
        if(!map.keySet().contains(ch)){
            map.put(ch,1);
        }else{
            map.put(ch,map.get(ch)+1);
        }
    }
  //return the first appearence once char in current stringstream
    public char FirstAppearingOnce()
    {
        for(char ch:map.keySet()){
            if (map.get(ch)==1){
                return ch;
            }
        }
        return '#';
    }
}

另外一种解法:我们知道,ASCII码一共只有128个字符,那么我可以直接定义一个长度为128的数组,空间复杂度为O(n),时间复杂度控制在常数级别,每个位置直接对应相应的字符,因此不需要额外存储数据,每个位置的数据代表出现的次数,每个位置代表相应的字符。虽然我获取第一个只出现一次的元素需要一个while循环,但是这个循环不可能超过128,一般很快就可以拿到。

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 '#';
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值