LeetCode 1429. 第一个唯一数字

1429. 第一个唯一数字

给定一系列整数,插入一个队列中,找出队列中第一个唯一整数。

实现 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:队列 + 集合

算法逻辑

  1. 使用一个队列来存储输入的整数序列。
  2. 使用两个集合,一个用来存储已经出现过的整数(set),另一个用来存储重复出现的整数(repeat)。
  3. 在初始化时,遍历输入的整数数组,将每个整数加入到队列和set中。如果某个整数已经在set中,则将其加入到repeat中。
  4. showFirstUnique方法需要检查队列的头部元素是否是唯一的。如果是,返回该元素;如果不是,从队列头部移除元素,直到找到唯一元素或队列为空。
  5. add方法用于向队列中添加新的整数。如果该整数已经在set中,则将其加入到repeat中;如果不在,则将其加入到set和队列中。

算法实现步骤

  1. 初始化:创建FirstUnique类的实例时,使用nums数组初始化队列、setrepeat
  2. 添加元素add方法首先检查新元素是否已经在set中。如果在,将其加入repeat;如果不在,将其加入set和队列。
  3. 显示唯一元素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是队列中元素的数量。
  • 10
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值