剑指offer第五十四题。
题目描述
请实现一个函数用来找出字符流中第一个只出现一次的字符。例如,当从字符流中只读出前两个字符"go"时,第一个只出现一次的字符是"g"。当从该字符流中读出前六个字符“google"时,第一个只出现一次的字符是"l"。
解题思路
常规的解法是用一个map来存储,这样空间复杂度为O(n),然后每次都遍历map获取第一个不重复的字符,时间复杂度也为O(n)。下面显示i代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| import java.util.Map; import java.util.LinkedHashMap; public class Solution { Map<Character,Integer> map = new LinkedHashMap<Character,Integer>(); public void Insert(char ch) { if(!map.containsKey(ch)){ map.put(ch,1); }else{ map.put(ch,map.get(ch)+1); } } public char FirstAppearingOnce() { for(char ch:map.keySet()){ int count = map.get(ch); if(count == 1) return ch; } return '#'; } }
|
这种很容易想到,但是能不能再优化一点呢?我们知道,ASCII码一共只有128个字符,那么我可以直接定义一个长度为128的数组,空间复杂度为O(n),时间复杂度控制在常数级别,虽然我获取第一个只出现一次的元素需要一个while循环,但是这个循环不可能超过128,一般很快就可以拿到。
我的答案
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| import java.util.LinkedList; public class Solution { int[] tmp = new int[128]; LinkedList<Character> queue = new LinkedList<>(); public void Insert(char ch) { if(tmp[ch-' '] == 0){ queue.add(ch); } tmp[ch-' ']++; } public char FirstAppearingOnce() { while(!queue.isEmpty() && tmp[queue.getFirst()-' ']>=2){ queue.removeFirst(); } if(!queue.isEmpty()){ return queue.getFirst(); } return '#'; } }
|