LeetCode 30 days Challenge - Day 28
本系列将对LeetCode新推出的30天算法挑战进行总结记录,旨在记录学习成果、方便未来查阅,同时望为广大网友提供帮助。
First Unique Number
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:
1 | Input: |
Example 2:
1 | Input: |
Example 3:
1 | Input: |
Constraints:
1 <= nums.length <= 10^5
1 <= nums[i] <= 10^8
1 <= value <= 10^8
- At most
50000
calls will be made toshowFirstUnique
andadd
.
Solution
题目要求分析:实现一个能够返回第一个唯一元素
的队列。要求实现:1.返回第一个唯一元素
的功能;2. 添加一个新元素。
解法:
本题重点需要理清,两个功能在各种不同的情况下,应该如何工作:
showFirstUnique()
:- 当队列为空,或没有唯一元素,返回
-1
; - 当队列存在唯一元素,返回第一个唯一的
元素值
。
- 当队列为空,或没有唯一元素,返回
add(int value)
:- 当队列不存在该元素,那么
加入队列
。 - 当队列存在该元素,那么将
原来的元素从队列中移除
,并且以后不能在加入该元素
。
- 当队列不存在该元素,那么
到这里,逻辑思路就整理完毕,接下来考虑数据结构使用问题。
- 为了
常量时间
访存,使用存在头尾指针的双向链表来存储唯一的元素
:- 每个元素初次出现都加入该链表,当重复的元素出现时,从该表移除,且不再加入该表,所以说存储的是“唯一的”元素。
- 第一个唯一元素即为第一个链表元素:
head->next == rear ? -1 : head->next->val
;此处注意对链表是否为空的判断。 - 当通过add加入新元素:新元素通过
尾插法
加入链表,不会打乱原有的相对顺序。 - 当出现重复元素,删除某一节点时:参见代码
removeNode(ListNode* node)
处。
- 为了
常量时间
判断元素存在,建立从value到链表指针的映射unordered_map<int, ListNode*> m
:- 添加一个元素时,通过
m.find(value) != m.end()
判断元素是否存在。 - 若不存在,新建链表结点、插入链表中、将指针赋给
m[value]
,这样可以通过常量时间访问到该value对应的链表结点。 - 为了实现“
以后不能在加入该元素
”的功能,当出现重复元素时,从链表中删除原元素后,将m[value]
指向NULL
,未来再次遇到该元素时就不会再次进行删除元素操作(已经不存在该元素,删除操作会造成错误)。
- 添加一个元素时,通过
本题值得细品,勿只读解法,务必参考代码,整理清楚逻辑。
1 | class FirstUnique { |
Karl