让
S
成为可能重叠的自然数的一组区间(包含n个区间),N是一个数字列表(包含n个数字)。
我想找到S的最小子集(让我们调用P),以便每个数字 在我们的列表N中,P中至少存在一个包含它的间隔。允许P中的间隔重叠。
琐碎的例子:
S = {[1..4], [2..7], [3..5], [8..15], [9..13]}
N = [1, 4, 5]
// so P = {[1..4], [2..7]}
我认为动态算法可能永远不会起作用,所以如果有人知道这个问题的解决方案(或类似的可以转换成的问题),那就太好了。我正在尝试制作O(n ^ 2解决方案)
这是一种贪婪的方法
P = {}
for each q in N: // O(n)
if q in P // O(n)
continue
for each i in S // O(n)
if q in I: // O(n)
P.add(i)
break
但那是O(n ^ 4)..任何有关创建O(n ^ 2)贪婪方法的帮助都会很棒!
谢谢!
*更新:* 我一直在抨击这个问题而我认为我有一个O(n ^ 2)解决方案!!
如果你认为我是对的,请告诉我。
N = MergeSort (N)
upper, lower = infinity, -1
P = empty set
for each q in N do
if (q>=lower and q<=upper)=False
max_interval = [-infinity, infinity]
for each r in S do
if q in r then
if r.rightEndPoint > max_interval.rightEndPoint
max_interval = r
P.append(max_interval)
lower = max_interval.leftEndPoint
upper = max_interval.rightEndPoint
S.remove(max_interval)
我认为这应该有用!!我试图找到一个反制解决方案;但是啊!
答案 0 :(得分:1)
这个问题类似于集合覆盖问题,它是NP完全的(即可以说没有比指数更快的解决方案)。区别在于区间总是覆盖相邻元素(而不是N的任意子集),这为更快的解决方案开辟了道路。
http://en.wikipedia.org/wiki/Set_cover_problem
我认为迈克提出的解决方案已经足够好了。但我想我有一个非常简单的O(N ^ 2)贪婪的算法。它开始像迈克的那个(而且,我相信迈克的解决方案也可以用类似的方式改进):
您对N个数字进行排序并将它们分类到数组ELEM中;复杂度O(N * lg N);
使用二分搜索,对于每个区间S [i],您可以识别S [i]所涵盖的ELEM中元素的起始和结束索引。比方说,你把这对数字放到数组COVER中,两个索引之间的差异告诉你你覆盖了多少元素,为简单起见,让我们把它放在数组COVER_COUNT;复杂度O(N * lg N);
引入索引指针p,显示ELEM中的哪个元素,你的N已被覆盖。你设置p = 0,意味着最初覆盖所有元素(排除在外)(即没有元素);复杂性O(1)。此外,您引入了布尔数组IS_INCLUDED,它反映了区间S [i]是否已包含在您的coverage集中。复杂性O(N)
然后从ELEM中的第0个元素开始,看看包含ELEM [0]的间隔是多少,覆盖范围更大COVER_COUNT [i]。想象一下,它是第i个间隔。然后我们通过将IS_INCLUDED [i]设置为true将其标记为包含。然后将p设置为end [i] + 1,其中end [i]是COVER [i]对中的结束索引(实际上现在所有元素直到end [i]都被覆盖)。然后,知道你更新COVER_COUNT中的所有元素,以便它们反映每个间隔覆盖的未覆盖元素的元素数量(这可以在O(N)时间内轻松完成)。然后对ELEM执行相同的步骤[p]并继续直到p> = ELEM.length。可以观察到总体复杂度为O(N ^ 2)。
你完成O(n ^ 2)并且IS_INCLUDED对于最佳封面集中包含的S的间隔是真的
让我知道这个解决方案对你来说是否合理,以及我是否计算好一切。
P.S。只是想补充说,算法找到的解决方案的最优性可以通过归纳和矛盾来证明。通过矛盾,很容易证明至少一个最优解包括那些覆盖元素ELEM [0]的最长间隔。如果是这样,通过归纳我们可以证明,对于算法中的每个下一个元素,我们可以继续遵循选择相对于覆盖的剩余元素数量最长的区间的策略,并且覆盖最左边但未覆盖的元素。
答案 1 :(得分:0)
我不确定,但有些人认为是这样的。
1)对于每个区间创建一个列表,其中N
包含的元素包含在间隔中,O(n^2)
可以将Q[i]
称为S[i]
2)然后按S
,Q[i]
的长度对O(n*lg(n))
进行排序
3)从Q[i]
N
和O(n)
= Q[i+1]...Q[n]
开始抛弃此数组,不包括O(n^2)
4)当N
不为空时重复2。
它不是O(n^2)
,而是O(n^3)
,但如果您可以使用hashmap,我认为您可以改进这一点。