给定一些整数范围,从每个范围中找到一个包含至少一个整数的最小集合

Posted

技术标签:

【中文标题】给定一些整数范围,从每个范围中找到一个包含至少一个整数的最小集合【英文标题】:Given some integer ranges, finding a smallest set containing at least one integer from each range 【发布时间】:2013-02-21 14:40:47 【问题描述】:

我怎样才能找到一组最小数量的整数,使得对于某些给定的整数范围,对于每个范围,该集合至少包含一个整数。例如,如果给我这些范围:

[0, 4], [1, 2], [5, 7], [6, 7], [6, 9], [8, 10]

然后一些解决方案集是: 1, 6, 8 , 2, 7, 9 , 1, 7, 8 等。

【问题讨论】:

【参考方案1】:

假设您绘制所有范围,按最终值排序,就像您在日程安排器中绘制会议一样。

您可以以贪婪的方式直观地选择您的数字,这样第一个就是最先完成的段(在您的示例中,这将是 2)。

然后删除所有包含该数字的段,然后重新开始。

这个算法将产生解决方案 2, 7, 10

0  1  2  3  4  5  6  7  8  9 10
   ----
-------------
      ^        -------
      |           ----
                  ----------
                     ^  -------
                     |        ^
                              |

【讨论】:

【参考方案2】:

算法: 对起点和终点进行排序。越过它们,直到遇到端点。将其添加到答案中并删除所有起点已经通过的范围(即包含当前端点的范围)。重复,直到剩下一点。

示例:

[0, 4], [1, 2], [5, 7], [6, 7], [6, 9], [8, 10]

排序后会变成

[0, [1, 2], 4], [5, [6, [6, 7], 7], [8, 9], 10], ans = []

第一个端点是2],我们将它添加到ans 并删除在它之前打开的范围,即[0[1

[5, [6, [6, 7], 7], [8, 9], 10], ans = [2]

现在第一个端点是7],我们删除范围[5, 7], [6, 7], [6, 9]

[8, 9], ans = [2, 7]

最后添加9 并删除最后一个范围。结果将是[2, 7, 9]

复杂性:

排序将花费 O(nlogn) 时间,之后您将传递每个元素两次:一次是在寻找下一个端点时,一次是在删除所有当前打开的间隔时,这是线性的,总复杂度将为 O(nlogn)这来自排序。

【讨论】:

除了将起点和终点排序在一起,我们还可以这样做:根据终点对 (start, end) 对进行排序。然后从头开始扫描。首先,我们存储第一对的端点,并将其添加到解决方案集中。然后,只要对的起点低于存储的端点,我们就向前扫描。每当我们找到一个起点大于该存储点的对时,我们将该对的端点添加到解决方案集中,并存储该端点以代替先前存储的点。我们继续这个处理直到最后一对。【参考方案3】:

我们按结束数字对区间进行排序。对于任何一个区间,如果它的起点不大于前一个终点,(由于区间已经排序,终点不小于前一个终点),那么我们在前一个终点有重叠,可以跳过这个区间。如果当前区间的开始大于前一个结束,我们没有重叠,将当前结束添加到结果集中。

考虑区间(0, 3), (2, 6), (3, 4), (6, 10)。排序后,我们有(0, 3), (3, 4), (2, 6), (6, 10)。我们从result = [3]previous = 3 开始。由于3 <= previous,我们跳过了区间(3, 4)previous 保持不变。由于2 <= previous,我们跳过区间(2, 6)previous 保持不变。最后,由于6 > previous,我们将10 添加到结果中,并更新previous = 10。算法终止;答案是[3, 10]

时间复杂度:n log(n),其中n 是区间数。

【讨论】:

以上是关于给定一些整数范围,从每个范围中找到一个包含至少一个整数的最小集合的主要内容,如果未能解决你的问题,请参考以下文章

如何检查整数是否在给定范围的集合中? [关闭]

数的范围(整数二分)

数的范围

二分算法(以 数的范围 为例)

在数组中搜索特定范围内的整数

如何从给定数组的范围查询中获取给定值的最小异或值