【数据结构和算法】无限集中的最小数字

简介: 这是力扣的2336题,难度为中等,解题方案有很多种,本文讲解我认为最奇妙的一种。使用TreeSet和min变量来维护一个无限集合,保证集合的连续性。添加元素时,若元素大于等于min,则不添加;若元素小于min,则将其添加到TreeSet中。删除元素时,先判断TreeSet是否为空,若不为空,则从TreeSet中删除元素;若为空,则将min值加1。该算法能够高效地添加和删除元素,并保持集合的连续性。该算法还可以用优先队列(小根堆)+ hash表解题,比较优秀。

 其他系列文章导航

Java基础合集

设计模式合集

多线程合集

分布式合集

ES合集


文章目录

其他系列文章导航

文章目录

前言

一、题目描述

二、题解

三、代码

四、总结


前言

这是力扣的2336题,难度为中等,解题方案有很多种,本文讲解我认为最奇妙的一种。


一、题目描述

现有一个包含所有正整数的集合 [1, 2, 3, 4, 5, ...]

实现 SmallestInfiniteSet 类:

    • SmallestInfiniteSet() 初始化 SmallestInfiniteSet 对象以包含 所有 正整数。
    • int popSmallest()移除 并返回该无限集中的最小整数。
    • void addBack(int num) 如果正整数 num 存在于无限集中,则将一个 num添加 到该无限集中。

    示例:

    输入

    ["SmallestInfiniteSet", "addBack", "popSmallest", "popSmallest", "popSmallest", "addBack", "popSmallest", "popSmallest", "popSmallest"]

    [[], [2], [], [], [], [1], [], [], []]

    输出

    [null, null, 1, 2, 3, null, 1, 4, 5]


    解释

    SmallestInfiniteSet smallestInfiniteSet = new SmallestInfiniteSet();

    smallestInfiniteSet.addBack(2);    // 2 已经在集合中,所以不做任何变更。

    smallestInfiniteSet.popSmallest(); // 返回 1 ,因为 1 是最小的整数,并将其从集合中移除。

    smallestInfiniteSet.popSmallest(); // 返回 2 ,并将其从集合中移除。

    smallestInfiniteSet.popSmallest(); // 返回 3 ,并将其从集合中移除。

    smallestInfiniteSet.addBack(1);    // 将 1 添加到该集合中。

    smallestInfiniteSet.popSmallest(); // 返回 1 ,因为 1 在上一步中被添加到集合中,

                                      // 且 1 是最小的整数,并将其从集合中移除。

    smallestInfiniteSet.popSmallest(); // 返回 4 ,并将其从集合中移除。

    smallestInfiniteSet.popSmallest(); // 返回 5 ,并将其从集合中移除。

    提示:

      • 1 <= num <= 1000
      • 最多调用 popSmallestaddBack 方法 共计1000

      二、题解

      这题的关键点是始终要保证无限集合是连续的。无限集合的范围可以认为是从 1 到正无穷大,并且都是正整数。

      这道我是用TreeSet和一个min变量来维护这个无限集合。为什么用TreeSet,因为TreeSet支持维护元素的自然顺序。

      TreeSet:小于min的有序集合。

      min:有序集合的最小值。

      添加元素的时候分为两种情况:

        1. 添加元素的时候如果添加的值大于等于无限集合中的最小值 min ,就不要添加,因为无限集合是连续的,添加的元素在无限集合中已经存在。(简单点说:比min还大的数不用加,说明已经存在了)
        2. 添加的元素如果小于无限集合的最小值 min 也不能直接添加,如果贸然添加会导致无限集合不连续,只需要把它添加到有序集合 TreeSet 中即可, TreeSet 中存放的值都是小于 min 的。所以要加在TreeSet中,要靠TreeSet来维护。

        删除元素的时候:

          1. 删除的时候先判断有序集合 TreeSet 是否为空,如果不为空,说明存在比 min 还小的元素,直接从 TreeSet 中删除。否则就从有序集合中删除 min ,删除之后 min 值要加 1 。

          三、代码

          class SmallestInfiniteSet {
              TreeSet<Integer> set = new TreeSet<>();
              int min = 1;
              public SmallestInfiniteSet() {}
              public int popSmallest() {
                  if (set.isEmpty()) {
                      return min++;//先返回,再++
                  }
                  return set.pollFirst();//弹出set的第一个元素,并删除
              }
              public void addBack(int num) {
                  if (num < min) {//大于的话,说明存在了
                      set.add(num);
                  }
              }
          }

          image.gif


          四、总结

          使用TreeSet和min变量来维护一个无限集合,保证集合的连续性。添加元素时,若元素大于等于min,则不添加;若元素小于min,则将其添加到TreeSet中。删除元素时,先判断TreeSet是否为空,若不为空,则从TreeSet中删除元素;若为空,则将min值加1。该算法能够高效地添加和删除元素,并保持集合的连续性。

          该算法还可以用优先队列(小根堆)+ hash表解题,比较优秀。

          目录
          相关文章
          |
          1天前
          |
          算法
          【初阶数据结构】复杂度算法题篇
          该方法基于如下的事实:当我们将数组的元素向右移动 k 次后,尾部 kmodn 个元素会移动至数组头部,其余元素向后移动 kmodn 个位置。
          |
          2天前
          |
          机器学习/深度学习 人工智能 算法
          【人工智能】线性回归模型:数据结构、算法详解与人工智能应用,附代码实现
          线性回归是一种预测性建模技术,它研究的是因变量(目标)和自变量(特征)之间的关系。这种关系可以表示为一个线性方程,其中因变量是自变量的线性组合。
          11 2
          |
          23天前
          |
          存储 算法 索引
          算法与数据结构
          算法与数据结构
          26 8
          |
          1天前
          |
          算法
          【初阶数据结构篇】二叉树算法题
          二叉树是否对称,即左右子树是否对称.
          |
          1天前
          |
          算法 索引
          【初阶数据结构篇】单链表算法题进阶
          深拷贝应该正好由 n 个全新节点组成,其中每个新节点的值都设为其对应的原节点的值。
          |
          1天前
          |
          存储 算法
          【初阶数据结构篇】顺序表和链表算法题
          此题可以先找到中间节点,然后把后半部分逆置,最近前后两部分一一比对,如果节点的值全部相同,则即为回文。
          |
          1月前
          |
          机器学习/深度学习 存储 算法
          【数据结构】算法的复杂度
          算法的时间复杂度和空间复杂度
          38 1
          【数据结构】算法的复杂度
          |
          27天前
          |
          搜索推荐 算法
          【数据结构】排序算法——Lesson2
          【7月更文挑战第24天】
          14 3
          |
          3天前
          |
          存储 缓存 算法
          深入解析B树:数据结构、存储结构与算法优势
          深入解析B树:数据结构、存储结构与算法优势
          |
          1月前
          |
          存储 算法 Python
          “解锁Python高级数据结构新姿势:图的表示与遍历,让你的算法思维跃升新高度
          【7月更文挑战第13天】Python中的图数据结构用于表示复杂关系,通过节点和边连接。常见的表示方法是邻接矩阵(适合稠密图)和邻接表(适合稀疏图)。图遍历包括DFS(深度优先搜索)和BFS(广度优先搜索):DFS深入探索分支,BFS逐层访问邻居。掌握这些技巧对优化算法和解决实际问题至关重要。**
          21 1