当前位置: 首页 > 知识库问答 >
问题:

计算不被任何一组区间覆盖的最小正整数

孙星鹏
2023-03-14

几周前有人在这里发布了这个问题,但它看起来非常像没有事先研究的家庭作业,OP在获得一些反对票后立即删除了它。

不过,这个问题本身很有趣,我已经想了一个星期,没有找到令人满意的解决方案。希望有人能帮忙?

问题如下:给定一个N个整数间隔的列表,其边界可以取从0的任何值,找到最小的整数i使得i不属于任何输入间隔。

例如,如果给定列表(N=4),则算法应返回9。

我能想到的最简单的解决方案运行在O(n log(n))中,它包括三个步骤:

  • 通过增加下限对间隔进行排序
    • 如果最小下界是

    这个简单的解决方案运行在O(n log(n))中,但最初的海报写道,算法应该运行在O(n)中。如果已经对间隔进行了排序,那么这很简单,但OP给出的示例包括未排序的间隔。我想这一定与N³有关,但我不确定是什么。。。散列?线性时间排序?欢迎提出想法。

    以下是上述算法的粗略python实现:

    def merge(first, second):
        (a, b), (c, d) = first, second
        if c <= b + 1:
            return (a, max(b, d))
        else:
            return False
    
    def smallest_available_integer(intervals):
        # Sort in reverse order so that push/pop operations are fast
        intervals.sort(reverse = True)
    
        if (intervals == [] or intervals[-1][0] > 0):
            return 0
    
        while len(intervals) > 1:
            first = intervals.pop()
            second = intervals.pop()
    
            merged = merge(first, second)
            if merged:
                print("Merged", first, "with", second, " -> ", merged)
                intervals.append(merged)
            else:
                print(first, "cannot be merged with", second)
                return first[1] + 1
    
    print(smallest_available_integer([(3,5), (2,8), (0,3), (10,13)]))
    

    输出:

    Merged (0, 3) with (2, 8)  ->  (0, 8)
    Merged (0, 8) with (3, 5)  ->  (0, 8)
    (0, 8) cannot be merged with (10, 13)
    9
    

共有2个答案

慕震博
2023-03-14

另一个想法是以某种方式使用这些间隔的补码。假设C()为您提供了一个区间的补码,例如C([3,5])将是小于3和大于5的整数。如果最大值为N^3,那么使用模N^3 1,甚至可以将其表示为另一个间隔[6,(N^3 1)2]。

如果您想要一个不属于任何原始区间的数字,那么这些区间的所有补码中都应该存在相同的数字。然后,它归结为编写一个函数,可以计算任何两个这样的“补码区间”的交点。

我还没有实现这个想法,因为我的纸笔图纸表明,在计算这样的交集时需要考虑的情况比我最初想象的要多。但我认为这背后的想法是有效的,它会导致O(n)算法。

编辑

经过进一步思考,有一个最坏的情况,使事情比我原先想象的更复杂。

亢奇
2023-03-14

详细说明@mrip的评论:您可以在O(n)时间内使用您描述的精确算法,但更改排序算法的工作方式。

通常,基数排序使用基数2:根据元素的位是0还是1将元素分成两个不同的桶。每轮基数排序需要时间O(n),并且每位有一轮最大的数字。调用最大的nunber U,这意味着时间复杂度为O(n log U)。

但是,您可以将基数排序的基数更改为其他基数。使用基b,每一轮都需要时间O(nb),因为初始化和迭代bucket需要时间O(b),将元素分配到bucket需要时间O(n)。然后是对数b轮。这给出了O的运行时间((n b)logbU)。

这里的诀窍是,由于最大数字U=n3,您可以设置b=n并使用基数n排序。现在轮数为lognU=lognn3,每轮需要O(n)个时间,因此对数字进行排序的总工作量为O(n)。更一般地说,对于任意k,可以在时间O(kn)内对[0,nk]范围内的数字进行排序。如果k是固定常数,则这是O(n)时间。

结合原始算法,这在时间O(n)内解决了问题。

希望这有帮助!

 类似资料:
  • [2,30],[25,39],[30,40]溶胶[2,30]

  • 我试图找出一种算法来寻找二部图的最小顶点覆盖。 我在考虑一个解决方案,将问题简化为二部图中的最大匹配。众所周知,可以使用从bip创建的networ中的最大流量来找到它。图表 最大匹配M应该决定最小。顶点覆盖C,但我无法处理选择要设置C的顶点。假设bip。图有部分X、Y,作为最大匹配边endpoint的顶点在集合A中,那些不属于B的顶点。 我会说,我应该为M到C中的边选择一个顶点。特别是M中的边e的

  • 我正在使用Spring Boot 2.1.6.RELEASE,我想知道应该如何使用? 配置示例: 和位于不同的模块中。 错误: 无法注册在类路径资源[com/example/autoconf/configuration/app configuration . class]中定义的bean“foo”。已在类路径资源[com/my/configuration/myautoconfiguration .

  • 程序屏幕截图 我正在制作动画。当我按下按钮时,它会触发一个动画,使从右侧浮动。当鼠标离开时JPanel退出动画),但问题是我在动画上有一个。因此,当我将鼠标移出动画时,面板不仅会消失,而且当我在按钮(这是面板的一个组件)上移动鼠标时,面板也会消失,这意味着当我想单击按钮时,它会消失,因为当鼠标离开时,就会被触发。 请看上面的图片,我在其中标记了某些区域。 < li >是JPanel,当我将鼠标移到

  • 我正在尝试以下练习来提高我的在线技能,我遇到了以下问题。 这是一个演示任务。 编写一个函数:class Solution{public int Solutions(int[]A);},给定一个包含N个整数的数组A,返回A中没有出现的最小正整数(大于0)。 举个例子, 给定 A = [1, 3, 6, 4, 1, 2],函数应返回 5。给定 A = [1, 2, 3],函数应返回 4。给定 A =

  • 在笛卡尔坐标中,我有一个知道高度h、宽度w和4个角(x, y)的矩形。如果我有一些值r,即圆的固定半径,如何计算将完全覆盖矩形的最小数量的圆的中心点?