# 【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++`