我要解决的问题在数字行上有一个间隔列表,每个间隔都有一个预定义的分数。我需要返回最大可能的总成绩。
问题是间隔重叠,在重叠间隔中我只能使用一个。这是一个例子。
Intervals - Score 0- 5 - 15 4- 9 - 18 10-15 - 12 8-21 - 19 25-30 - 25
在此,间隔0-5、4-9和8-21重叠。 间隔10-15和8-21也重叠。 最大和为55(18 + 12 + 25)。
重要的是要在这里注意,我们选择的第一批重叠间隔的间隔4-9,即使它没有三者中最高的得分。
这是因为选择间隔8-21将阻止我们以后再使用间隔10-15,从而减少了总和(在这种情况下,总和将为19 + 25 = 44)。
我正在寻找此问题的O(nlogn)或O(n)解决方案。我认为可以使用动态编程,但我可能是错的。有人可以提出可以解决问题的解决方案/算法吗?
编辑:间隔没有特定的顺序。
这是间隔调度的加权变化; 它可以O(N log N)通过动态编程解决。
O(N log N)
设一个间隔g(start, stop, score),然后按排序stop。为了简单起见,让我们现在假设所有stop都是唯一的。
g(start, stop, score)
stop
让我们best[i]成为允许使用时可获得的最佳分数g[1], ..., g[i]。当然,我们不必全部使用它们,而且通常也不能,因为我们使用的间隔子集必须不重叠。
best[i]
g[1], ..., g[i]
best[0] = 0
1 <= k <= N
best[k] = max( best[k-1], best[j] + g[k].score )
j
g[j].stop < g[k].start
也就是说,考虑到我们被允许使用g[1], ... g[k],我们可以做的最好的事情就是对这两个选项进行更好的评分:
g[1], ... g[k]
g[k]
best[k-1]
g[1], ... g[k-1]
g[1], ..., g[j]
best[j] + g[k].score
(请注意上式中体现的动态编程的最佳子结构和重叠子问题组件)。
这个问题的总体答案是best[N],即,当我们允许使用所有基因时,我们可以得到的最高分数。糟糕,我说过基因吗?我的意思是间隔。
best[N]
这是O(N log N)因为:
k
O(log N)
如果几个基因可以具有相同的stop值,那么什么都没有改变:您仍然必须搜索最右边的j。在例如Python中,使用会很容易bisect_right。在Java中,标准库二进制搜索不能保证在有关联的情况下返回哪个索引,因此您可以(在许多选项中)进行线性搜索(以获取O(N)最坏情况的性能)或其他一系列二进制搜索来查找最正确的索引。
bisect_right
O(N)
糟糕,我又说了基因?我的意思是间隔。
`