Try   HackMD

【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
  • 最多呼叫50000showFirstUniqueadd.

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

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++