以下是某人给我的一个练习面试问题,我不确定最佳解决方案是什么到这是:给定一组范围S和一个重叠范围R,找到S中包含R的最小子集。
给定一组范围:
(例如S = {(1, 4), (30, 40), (20, 91) ,(8, 10), (6, 7), (3, 9), (9, 12), (11, 14)}
并给予的目标范围R(例如R = (3, 13)
- 这意味着要为3〜13)的范围内写的算法。找到覆盖目标范围的最小范围集合,集合中的所有范围必须重叠才能被视为跨越范围整个目标范围。 (在这个例子中,答案会是{(3, 9), (9, 12), (11, 14)}
。
什么是解决呢?我想,这将使用贪心算法来做到最好。在上面的例子中,我们会寻找所有与3相交的数字,然后从那些最高的那个中挑选出来,然后我们会用刚才选择的那个做同样的事情,因此,我们选择了(3,9),现在我们想要找到所有在这些迭代中,我们选择了(9,12),我们对该问题做了同样的事情,我们发现下一个相交的范围是12 ,最高的是(11,14)。
在迭代之后,我们看到14大于13(我们范围的最大值),所以我们可以停止。
我对这个算法的问题是,如何有效地查询相交范围?如果我们尝试线性搜索,我们最终得到的算法是O(n^2)
。我的下一个想法是在我们每次运行循环时将我们列表中的任何交叉范围截断。因此,在第一次迭代中,我们穿过(1,4)和(3,9)。在我们的下一次迭代中,我们穿过(9,12),(3,9)和(8,10)。因此,通过最后一次迭代,我们必须查看的是{(30,40),(20,91),(6,7)}。我们也可以通过将所有有> 13和最大值的所有东西都划掉,从而提高效率。3.问题是这仍然可能不够。在我们的范围内有很多重复的序列仍然存在潜在的问题。如果我们的范围列表包含诸如{(6,7),(6,7),(6,7),(6,7),(6,7)},我们将不得不每次查看这些尽管它们对我们没有用处。即使我们只是存储唯一值(通过将它们全部放入一组中),我们可能会有一个非常大的范围,并且有一系列范围在我们的目标范围内,但是我们也有一个范围在几乎范围内整个目标范围。
什么将是一种有效的方式来查询我们的范围?或者,可能会有什么更有效的算法来解决这个问题?
能有效溶液包括'(8,10)'? –
该组的成员必须重叠。如果他们没有,他们不会跨越整个范围。所以如果我们包含'(8,10)',它仍然必须包含'(9,12)'。如果我们这样做了,它将是一个大小为4的集合,而不是大小为3的集合。因此它不再是覆盖范围'(3,13)'的最小可能范围集合。 – Ephraim