import java.util.*; import java.util.stream.IntStream; /** * NC277 字符流中第一个不重复的字符 * @author d3y1 */ public class Solution { private HashSet<Character> appearSet = new HashSet<>(); private HashSet<Character> firstSet = new HashSet<>(); private HashMap<Character, Integer> map = new HashMap<>(); private Queue<Character> queue = new LinkedList<>(); private HashMap<Character, Integer> linkedMap = new LinkedHashMap<>(); private StringBuilder seq = new StringBuilder(); // ASCII码 private int[] count = new int[128]; // 字符首次出现的位置 private int location = 0; private int[] array = IntStream.generate(() -> -1).limit(128).toArray(); // 字符出现的位置 int[] index = new int[128]; // 用于标记字符流的位置 int at = 0; /** * Insert: Insert one char from string stream * @param ch */ public void Insert(char ch) { // Insert1(ch); // Insert2(ch); // Insert3(ch); // Insert4(ch); // Insert5(ch); // Insert6(ch); Insert7(ch); } /** * FirstAppearingOnce: return the first appearance once char in current string stream * @return */ public char FirstAppearingOnce() { // return FirstAppearingOnce1(); // return FirstAppearingOnce2(); // return FirstAppearingOnce3(); // return FirstAppearingOnce4(); // return FirstAppearingOnce5(); // return FirstAppearingOnce6(); return FirstAppearingOnce7(); } /** * Insert1: HashSet + HashMap + Queue * @param ch */ private void Insert1(char ch){ if(appearSet.contains(ch)){ if(firstSet.contains(ch)){ firstSet.remove(ch); } }else{ appearSet.add(ch); firstSet.add(ch); queue.offer(ch); } map.put(ch, map.getOrDefault(ch, 0)+1); } /** * FirstAppearingOnce1: HashSet + HashMap + Queue * @return */ private char FirstAppearingOnce1(){ if(!firstSet.isEmpty()){ while(!queue.isEmpty() && !firstSet.contains(queue.peek())){ queue.poll(); } if(!queue.isEmpty()){ return queue.peek(); } } return '#'; } /** * Insert2: LinkedHashMap => 保证key的先后顺序 * @param ch */ private void Insert2(char ch){ linkedMap.put(ch, linkedMap.getOrDefault(ch, 0)+1); } /** * FirstAppearingOnce2: LinkedHashMap => 保证key的先后顺序 * @return */ private char FirstAppearingOnce2(){ for(Character ch: linkedMap.keySet()){ if(linkedMap.get(ch) == 1){ return ch; } } return '#'; } /** * Insert3: HashMap + StringBuilder * @param ch */ private void Insert3(char ch){ seq.append(ch); map.put(ch, map.getOrDefault(ch, 0)+1); } /** * FirstAppearingOnce3: HashMap + StringBuilder * @return */ private char FirstAppearingOnce3(){ for(int i = 0; i < seq.length(); i++){ if(map.get(seq.charAt(i)) == 1){ return seq.charAt(i); } } return '#'; } /** * Insert4: HashMap + Queue * @param ch */ private void Insert4(char ch){ if(!map.containsKey(ch)){ queue.offer(ch); } map.put(ch, map.getOrDefault(ch, 0)+1); } /** * FirstAppearingOnce4: HashMap + Queue * @return */ private char FirstAppearingOnce4(){ while(!queue.isEmpty()){ if(map.get(queue.peek()) == 1){ return queue.peek(); }else{ queue.poll(); } } return '#'; } /** * Insert5: BitMap + Queue * @param ch */ private void Insert5(char ch){ if(count[ch]++ == 0){ queue.offer(ch); }else{ queue.remove(ch); } } /** * FirstAppearingOnce5: BitMap + Queue * @return */ private char FirstAppearingOnce5(){ if(queue.isEmpty()){ return '#'; } return queue.peek(); } /** * Insert6: BitMap + location * @param ch */ private void Insert6(char ch){ // 首次出现 if(array[ch] == -1){ array[ch] = location++; }else{ array[ch] = -2; } } /** * FirstAppearingOnce6: BitMap + location * @return */ private char FirstAppearingOnce6(){ int minIndex = Integer.MAX_VALUE; char ch = '#'; for(int i = 0; i < 128; i++){ if(array[i]>=0 && array[i]<minIndex){ ch = (char) i; minIndex = array[i]; } } return ch; } /** * Insert7: Double BitMap * @param ch */ private void Insert7(char ch){ count[ch]++; index[ch] = at++; } /** * FirstAppearingOnce7: Double BitMap * @return */ private char FirstAppearingOnce7(){ int minIndex = at; char ch = '#'; for(int i = 0; i < 128; i++){ if(count[i]==1 && index[i]<minIndex){ ch = (char) i; minIndex = index[i]; } } return ch; } }