You have a queue of integers, you need to retrieve the first unique integer in the queue.
Implement the FirstUnique
class:
FirstUnique(int[] nums)
Initializes the object with the numbers in the queue.int showFirstUnique()
returns the value of the first unique integer of the queue, and returns -1 if there is no such integer.void add(int value)
insert value to the queue.
Example 1:
Input: ["FirstUnique","showFirstUnique","add","showFirstUnique","add","showFirstUnique","add","showFirstUnique"] [[[2,3,5]],[],[5],[],[2],[],[3],[]] Output: [null,2,null,2,null,3,null,-1] Explanation: FirstUnique firstUnique = new FirstUnique([2,3,5]); firstUnique.showFirstUnique(); // return 2 firstUnique.add(5); // the queue is now [2,3,5,5] firstUnique.showFirstUnique(); // return 2 firstUnique.add(2); // the queue is now [2,3,5,5,2] firstUnique.showFirstUnique(); // return 3 firstUnique.add(3); // the queue is now [2,3,5,5,2,3] firstUnique.showFirstUnique(); // return -1Example 2:
Input: ["FirstUnique","showFirstUnique","add","add","add","add","add","showFirstUnique"] [[[7,7,7,7,7,7]],[],[7],[3],[3],[7],[17],[]] Output: [null,-1,null,null,null,null,null,17] Explanation: FirstUnique firstUnique = new FirstUnique([7,7,7,7,7,7]); firstUnique.showFirstUnique(); // return -1 firstUnique.add(7); // the queue is now [7,7,7,7,7,7,7] firstUnique.add(3); // the queue is now [7,7,7,7,7,7,7,3] firstUnique.add(3); // the queue is now [7,7,7,7,7,7,7,3,3] firstUnique.add(7); // the queue is now [7,7,7,7,7,7,7,3,3,7] firstUnique.add(17); // the queue is now [7,7,7,7,7,7,7,3,3,7,17] firstUnique.showFirstUnique(); // return 17Example 3:
Input: ["FirstUnique","showFirstUnique","add","showFirstUnique"] [[[809]],[],[809],[]] Output: [null,809,null,-1] Explanation: FirstUnique firstUnique = new FirstUnique([809]); firstUnique.showFirstUnique(); // return 809 firstUnique.add(809); // the queue is now [809,809] firstUnique.showFirstUnique(); // return -1
题意是设计一个FirstUnique的class,包含一开始列出的三个函数。可以发现,因为没有删除操作,加入queue的数字从未被拿出来,但是每次需要返回的是第一个unique的数字。既然是找unique的数字,必然会牵涉到hashmap,所以我的思路是用一个hashmap记录每个数字及其他们各自的出现次数,同时创建一个queue,在做add操作的时候也是无条件将元素加入queue。但是在showFirstUnique中,如果queue里面头一个节点(peek)不是unique的,则弹出这个元素,直到找到一个unique的元素。这个思路可行但是时间复杂度不太理想。
时间O(n) - 有可能queue需要弹出很多元素之后才能找的到第一个unique value
空间O(n)
Java实现
1 class FirstUnique { 2 HashMap<Integer, Integer> map; 3 Queue<Integer> queue; 4 5 public FirstUnique(int[] nums) { 6 map = new HashMap<>(); 7 queue = new LinkedList<>(); 8 for (int num : nums) { 9 add(num); 10 } 11 } 12 13 public int showFirstUnique() { 14 while (!queue.isEmpty()) { 15 int num = queue.peek(); 16 int freq = map.get(num); 17 if (freq > 1) { 18 queue.poll(); 19 } else { 20 return num; 21 } 22 } 23 return -1; 24 } 25 26 public void add(int value) { 27 if (map.containsKey(value)) { 28 map.put(value, map.get(value) + 1); 29 } else { 30 map.put(value, 1); 31 queue.add(value); 32 } 33 } 34 } 35 36 /** 37 * Your FirstUnique object will be instantiated and called as such: 38 * FirstUnique obj = new FirstUnique(nums); 39 * int param_1 = obj.showFirstUnique(); 40 * obj.add(value); 41 */
网上看到一个更好的解法,思路差不多,但是用到了LinkedHashSet帮助记录unique value。思路是用一个hashset和一个LinkedHashSet记录元素,hashset首先还是在记录独一的元素,当遍历到重复元素后,hashset也只会返回false;LinkedHashSet因为是有序的,所以当遍历到重复元素的时候,需要把这个元素从LinkedHashSet中删去。这样在返回unique value的时候,时间上会省很多。
时间O(n),虽然返回unique的动作是O(1)但是add()函数在极端情况下也会很费时间
空间O(n)
Java实现
1 class FirstUnique { 2 Set<Integer> unique = new LinkedHashSet<>(); 3 Set<Integer> all = new HashSet<>(); 4 5 public FirstUnique(int[] nums) { 6 for (int num : nums) { 7 add(num); 8 } 9 } 10 11 public int showFirstUnique() { 12 if (unique.isEmpty()) { 13 return -1; 14 } 15 return unique.iterator().next(); 16 } 17 18 public void add(int value) { 19 if (all.add(value)) { 20 unique.add(value); 21 } else { 22 unique.remove(value); 23 } 24 } 25 } 26 27 /** 28 * Your FirstUnique object will be instantiated and called as such: 29 * FirstUnique obj = new FirstUnique(nums); 30 * int param_1 = obj.showFirstUnique(); 31 * obj.add(value); 32 */