解法一:HashMap+ArrayList

基本思路

  1. 用HashSet记录出现过至少一次的值,用ArrayList记录只出现过一次的值。
  2. insert每次在HashSet中查找 ch,如果没有,那么就往ArrayList中添加;如果有,就从ArrayList中删除 ch。(可能出现ArrayList中已经没有ch但依然要删除的情况,这是没有关系的,找不到ch, remove()会返回false)
  3. ArrayList中一定是按顺序存储着只出现过一次的值,那么每次FirstAppearingOnce()只用返回在ArrayList首位的字符即可。如果ArrayList为空,那么就返回'#'。

注意

list.remove((Character)ch);

这里的(Character)强制转换不能少,否则,char输入会直接被识别为整型变量。list.remove()就变成了按照位置删除了。

import java.util.*;
public class Solution {
    //Insert one char from stringstream
    public void Insert(char ch){
        if(!once.contains(ch)) {
            list.add(ch);
            once.add(ch);
        }
        else {
            list.remove((Character)ch);
        }
    }
  //return the first appearence once char in current stringstream
    List<Character> list=new LinkedList<>();
    Set<Character> once=new HashSet<>();
    public char FirstAppearingOnce(){
        if(list.size()>0) return list.get(0);
        return '#';
    }
}

解法二:HashMap+Queue

这道题的常见做法。
HashMap储存 字符和字符出现次数。(我直接用boolean表示 false:出现过一次, true:出现过一次以上。因为出现2、3、4...次的处理都是一样的,没有必要再往上+1了。)
Queue按顺序储存可能是仅出现过一次的字符,每一次FirstAppearingOnce()返回前要通过HashMap判断。

import java.util.*;
public class Solution {
    //Insert one char from stringstream
    Map<Character, Boolean> map=new HashMap<>();
    Queue<Character> q=new LinkedList<>();
    public void Insert(char ch){
        if(!map.containsKey(ch)){
            q.add(ch);
            map.put(ch,false);
        }else{
            map.put(ch,true);
        }
    }
  //return the first appearence once char in current stringstream
    public char FirstAppearingOnce(){
        while(!q.isEmpty()&&map.get(q.peek())){
            q.poll();
        }
        return q.isEmpty()? '#':q.peek();
    }
}