给定一系列整数,插入一个队列中,找出队列中第一个唯一整数。
实现 FirstUnique
类:
FirstUnique(int[] nums)
用数组里的数字初始化队列。int showFirstUnique()
返回队列中的 第一个唯一 整数的值。如果没有唯一整数,返回 -1。(译者注:此方法不移除队列中的任何元素)void add(int value)
将 value 插入队列中。
示例 1:
输入: ["FirstUnique","showFirstUnique","add","showFirstUnique","add","showFirstUnique","add","showFirstUnique"] [[[2,3,5]],[],[5],[],[2],[],[3],[]] 输出: [null,2,null,2,null,3,null,-1] 解释: FirstUnique firstUnique = new FirstUnique([2,3,5]); firstUnique.showFirstUnique(); // 返回 2 firstUnique.add(5); // 此时队列为 [2,3,5,5] firstUnique.showFirstUnique(); // 返回 2 firstUnique.add(2); // 此时队列为 [2,3,5,5,2] firstUnique.showFirstUnique(); // 返回 3 firstUnique.add(3); // 此时队列为 [2,3,5,5,2,3] firstUnique.showFirstUnique(); // 返回 -1
示例 2:
输入: ["FirstUnique","showFirstUnique","add","add","add","add","add","showFirstUnique"] [[[7,7,7,7,7,7]],[],[7],[3],[3],[7],[17],[]] 输出: [null,-1,null,null,null,null,null,17] 解释: FirstUnique firstUnique = new FirstUnique([7,7,7,7,7,7]); firstUnique.showFirstUnique(); // 返回 -1 firstUnique.add(7); // 此时队列为 [7,7,7,7,7,7,7] firstUnique.add(3); // 此时队列为 [7,7,7,7,7,7,7,3] firstUnique.add(3); // 此时队列为 [7,7,7,7,7,7,7,3,3] firstUnique.add(7); // 此时队列为 [7,7,7,7,7,7,7,3,3,7] firstUnique.add(17); // 此时队列为 [7,7,7,7,7,7,7,3,3,7,17] firstUnique.showFirstUnique(); // 返回 17
示例 3:
输入: ["FirstUnique","showFirstUnique","add","showFirstUnique"] [[[809]],[],[809],[]] 输出: [null,809,null,-1] 解释: FirstUnique firstUnique = new FirstUnique([809]); firstUnique.showFirstUnique(); // 返回 809 firstUnique.add(809); // 此时队列为 [809,809] firstUnique.showFirstUnique(); // 返回 -1
提示:
1 <= nums.length <= 10^5
1 <= nums[i] <= 10^8
1 <= value <= 10^8
- 最多调用
5000
次showFirstUnique
和add
。
提示 1
Use doubly Linked list with hashmap of pointers to linked list nodes. add unique number to the linked list. When add is called check if the added number is unique then it have to be added to the linked list and if it is repeated remove it from the linked list if exists. When showFirstUnique is called retrieve the head of the linked list.
提示 2
Use queue and check that first element of the queue is always unique.
提示 3
Use set or heap to make running time of each function O(logn).
解法1:队列 + 集合
算法逻辑
- 使用一个队列来存储输入的整数序列。
- 使用两个集合,一个用来存储已经出现过的整数(
set
),另一个用来存储重复出现的整数(repeat
)。 - 在初始化时,遍历输入的整数数组,将每个整数加入到队列和
set
中。如果某个整数已经在set
中,则将其加入到repeat
中。 showFirstUnique
方法需要检查队列的头部元素是否是唯一的。如果是,返回该元素;如果不是,从队列头部移除元素,直到找到唯一元素或队列为空。add
方法用于向队列中添加新的整数。如果该整数已经在set
中,则将其加入到repeat
中;如果不在,则将其加入到set
和队列中。
算法实现步骤
- 初始化:创建
FirstUnique
类的实例时,使用nums
数组初始化队列、set
和repeat
。 - 添加元素:
add
方法首先检查新元素是否已经在set
中。如果在,将其加入repeat
;如果不在,将其加入set
和队列。 - 显示唯一元素:
showFirstUnique
方法首先检查队列是否为空。如果不为空,检查队列头部元素是否在repeat
中。如果是,从队列中移除头部元素,直到找到唯一元素或队列为空。
Java版:
class FirstUnique {
Deque<Integer> queue;
Set<Integer> set;
Set<Integer> repeat;
public FirstUnique(int[] nums) {
queue = new ArrayDeque<>();
set = new HashSet<>();
repeat = new HashSet<>();
for (int num : nums) {
if (set.contains(num)) {
repeat.add(num);
} else {
set.add(num);
queue.offer(num);
}
}
}
public int showFirstUnique() {
while (repeat.contains(queue.peek())) {
queue.poll();
}
if (queue.isEmpty()) {
return -1;
}
return queue.peek();
}
public void add(int value) {
if (set.contains(value)) {
repeat.add(value);
} else {
set.add(value);
queue.offer(value);
}
}
}
/**
* Your FirstUnique object will be instantiated and called as such:
* FirstUnique obj = new FirstUnique(nums);
* int param_1 = obj.showFirstUnique();
* obj.add(value);
*/
Python3版:
class FirstUnique:
def __init__(self, nums: List[int]):
self.queue = deque()
self.set = set()
self.repeat = set()
for num in nums:
if num in self.set:
self.repeat.add(num)
else:
self.set.add(num)
self.queue.append(num)
def showFirstUnique(self) -> int:
while self.queue and self.queue[0] in self.repeat:
self.queue.popleft()
return -1 if not self.queue else self.queue[0]
def add(self, value: int) -> None:
if value in self.set:
self.repeat.add(value)
else:
self.set.add(value)
self.queue.append(value)
# Your FirstUnique object will be instantiated and called as such:
# obj = FirstUnique(nums)
# param_1 = obj.showFirstUnique()
# obj.add(value)
复杂度分析
- 时间复杂度:对于
add
操作,检查和添加到集合的时间复杂度为O(1)。对于showFirstUnique
操作,最坏情况下可能需要遍历整个队列,时间复杂度为O(n),其中n是队列的长度。 - 空间复杂度:由于我们需要存储队列中的所有元素以及两个集合,空间复杂度为O(n),其中n是队列中元素的数量。