# 【LeetCode】 First Unique Number ## Description > 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. > Constraints: > * `1 <= nums.length <= 10^5` > * `1 <= nums[i] <= 10^8` > * `1 <= value <= 10^8` > * At most `50000` calls will be made to `showFirstUnique` and `add`. > 你有一個整數組成的佇列,你需要找到在此佇列中第一個只有出現一次的整數。 > 實作`FirstUnique`類別: > * `FirstUnique(int[] nums)` 用一串數字佇列初始化該物件。 > * `int showFirstUnique()` 回傳佇列中第一個只有出現一次的整數,如果沒有這種數字回傳`-1` > * `void add(int value)` 新增一個新的數到佇列中。 > 限制: > * `1 <= nums.length <= 10^5` > * `1 <= nums[i] <= 10^8` > * `1 <= value <= 10^8` > * 最多呼叫`50000`次`showFirstUnique`和`add`. ## Example: ``` 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 -1 Example 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 17 Example 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 ``` ## Solution * 這一題是一個結構設計題,需要資料結構的基礎。 * 我們需要找到第一個只出現一次的數,因此我們需要一個linked-list來得到**第一個**這件事情。 * 我們需要新增新的元素,因此我們需要強化前面的linked-list,將它變為雙向鏈結,一頭是第一個,一頭是新增用的。 * 最後,為了快速地找到數字是否在之前已經插入過,我們需要一個hash去映射數字和鏈結的指標,才不需要每次新增的時候,都遍歷一次list。 --- * 接下來請搭配下面的code閱讀: * `unique`是一個list,儲存只出現一次的數字。 * `it`是一個加速用的hash,key是想要找的數字,value,是該數字在list中的指標。(用於快速刪除) * `allNums`是一個用於確認數字是否第一次出現的hash。 * 初始化就把數字都`add`進去就好了。 * `showFirstUnique`只要去找`unique`這個list就好了。 * `add`是最麻煩的部分,我們先確認`allNums`有沒有這個數字: * 如果沒有,將該數字加到`unique`裡面,並且把`it`綁上去。 * 如果有,先確認這個數字是第二次出現還是已經第三、四...次了。 * 如果是第二次,利用`it`映射過去,去`unique`找到並移除該數字。 * 如果已經不是第二次了,代表之前已經移除過了,就不用理它。 * 最後記得`allNums`的計數要加上去。 ### Code ```C++=1 class FirstUnique { public: list<int> unique; unordered_map<int, list<int>::iterator> it; unordered_map<int, int> allNums; FirstUnique(vector<int>& nums) { for(int i = 0; i < nums.size(); i++) { add(nums[i]); } } int showFirstUnique() { if(unique.empty()) return -1; return unique.back(); } void add(int value) { auto it_find = allNums.find(value); if(it_find == allNums.end()) { unique.push_front(value); it[value] = unique.begin(); } else { if(allNums[value] == 1) { auto pos = it[value]; unique.erase(pos); it.erase(value); } } allNums[value]++; } }; /** * Your FirstUnique object will be instantiated and called as such: * FirstUnique* obj = new FirstUnique(nums); * int param_1 = obj->showFirstUnique(); * obj->add(value); */ ``` ###### tags: `LeetCode` `C++`