一.题目描述
请实现一个函数用来找出字符流中第一个只出现一次的字符。例如,当从字符流中只读出前两个字符"go"时,第一个只出现一次的字符是"g"。当从该字符流中读出前六个字符“google"时,第一个只出现一次的字符是"l"。
输出描述:
如果当前字符流没有存在出现一次的字符,返回#字符。
二.程序代码
import java.util.Map;
import java.util.LinkedHashMap;
public class Solution {
public Map<Character,Integer> map=new LinkedHashMap<>();
//Insert one char from stringstream
public void Insert(char ch)
{
if(map.containsKey(ch)){
map.put(ch,map.get(ch)+1);
}else{
map.put(ch,1);
}
}
//return the first appearence once char in current stringstream
public char FirstAppearingOnce()
{
char ret='#';
for(Map.Entry<Character,Integer> e:map.entrySet()){
int count=e.getValue();
if(count==1){
return e.getKey();
}
}
return ret;
}
}
三.运行结果
输入数据:google
输出数据:ggg#ll
四.分析
从这个结果可以看出,题目要求输入一个字符流,其中Insert(char ch);函数是用来扩充字符流的,也就是说:
(1)如果当前字符流为g
输出g
(2)那么调用Insert(char ch)这个函数再插入一个字符o,那么当前字符流就变为了go
输出gg
(3)如果再调用Insert(char ch)这个函数再插入一个字符o,那么当前字符流就变为了goo
输出ggg
(4)如果再次调用Insert(char ch)这个函数再插入一个字符g,那么当前字符流就变为了goog
输出ggg#
(5)如果再次调用Insert(char ch)这个函数再插入一个字符l,那么当前字符流就变为了googl
输出ggg#l
由此可见,当前字符流是在上一个字符流上进行不断地增加一个字符而确定的。
因此,我们需要使用Map<Key,Value>来存储当前字符流的每个字符及相应的出现次数,分别作为Map的Key和Value。
而且要特别注意:
要用LinkedHashMap<>();来实现你的Map,这样才能保证你的Map中的元素顺序是按当前插入元素来排序的。
五.Map的构造函数的区别
1. LinkedHashMap
LinkedHashMap是继承HashMap类,,具有 HashMap 集合上面所说的所有特点,除了 HashMap 无序的特点,LinkedHashMap 是有序的,因为 LinkedHashMap 在 HashMap 的基础上单独维护了一个具有所有数据的双向链表,该链表保证了元素迭代的顺序。
LinkedHashMap定义了accessOrder变量,值为true表示按照访问顺序排序,值为false表示按照插入顺序排序。accessOrder的默认值为false,也就是按照插入顺序排序,所以本题选用这个构造函数来实现Map
2.TreeMap
TreeMap中的元素默认按照key的自然顺序排序。(对Integer来说,其自然排序就是数字的升序;对String来说,其自然排序就是按照字母进行排序)
3.HashMap
HashMap可实现快速存储和检索,但其缺点是其包含的元素是无序的,这导致它在存在大量迭代的情况下表现不佳。