LeetCode、2336. 无限集中的最小数字(中等,小顶堆)

发布时间:2024年01月16日

前言

博主所有博客文件目录索引:博客目录索引(持续更新)


LeetCode、2336. 无限集中的最小数字

题目链接及类型

题目链接:2336. 无限集中的最小数字

类型:数据结构/优先队列


思路

首先读题:包含有一个正整数的无限集合,如:集合 [1, 2, 3, 4, 5, ...] 。包含两个操作:①popSmallest:移除并得到一个集合中的最小元素。②addBack(int num):若是当前集合中不存在该元素num,则将该元素添加到集合中!【注意这里集合中是具有唯一性】

在这里我们选择小顶堆数据结构,第一个永远是集合中最小的元素,并且插入操作时间复杂度为O(logn),取得最小值复杂度为O(1)。

对于其中的无限正整数,我们可以使用一个变量thres来定义,初始值为1,是否需要提前将大量的数字填充到集合中呢?并不需要,若是在popSmallest时我们的小顶堆为空时,我们可以根据thres值来进行返回。若是进行addBack时,一旦填入的num值<thres才添加到集合中。

上面的思路有了,那么还要注意的一点就是在进行addBack时要防止num<thres情况多次进行调用,若是我们不判断唯一性,那么可能会将重复值多次添加到队列当中。所以这里我们会使用一个boolean的vis数组来表示是否访问过。


代码题解

复杂度分析:时间复杂度O(n.logn);空间复杂度O(n)

//注意:要考虑到元素的唯一性!!!也就是说在集合中无法同时存在两个元素值相同的元素
class SmallestInfiniteSet {

    public boolean[] vis;
    public PriorityQueue<Integer> queue;
    public int thres;

    public SmallestInfiniteSet() {
        this.vis = new boolean[1001];//题目说了num最大值为1000
        this.queue = new PriorityQueue<>((o1, o2)->o1.compareTo(o2));//小顶堆
        this.thres = 1;
    }
    
    public int popSmallest() {
        if (queue.isEmpty()) {
            int ans = thres;
            thres ++;
            return ans;
        }
        int ans = queue.poll();
        vis[ans] = false;
        return ans;
    }   
    
    //在进行添加时,当num<thres时,连续进行两次add调用,那么此时若是没有唯一性判断就会添加两个相同的元素到集合中
    //为了避免这种情况,就需要使用一个vis数组来表示唯一性
    public void addBack(int num) {
        if (num < thres && !vis[num]) {
            queue.offer(num);
            vis[num] = true;
        }
            
    }
}

image-20240116201143650


整理者:长路 时间:2024.1.15

文章来源:https://blog.csdn.net/cl939974883/article/details/135634275
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。