我最近参加了一个离线竞赛,他们问了这个问题。
给定n个区间,您必须找到一个存在最大间隔交叉点的点。
你可以这样做2次,所以间隔的总和应该是最大的。
EG。 n = 6,(1,3)(2,5)(4,8)(4,8)(3,7),(6,8)
如果我们第一次贪婪地选择4,我们将获得4个间隔重叠。
4:(2,5)(4,8)(4,8)(3,7)。
下次我们只能获得1,总共5。
(1,3)或(6,8)
但如果我们在第一个实例中选择2而在第二个实例中选择7,那么我们将得到6作为答案。
2:(1,3)(2,5)
7:(4,8)(4,8)(3,7),(6,8)
间隔可以在[1,10 ^ 9]和1 <= n <= 10 ^ 5
的范围内注意:两次表示,你可以做2次。您可以选择2个点,使得每个区间中的交点总和最大。就像您首先这样做,找到一组相交的范围,然后删除它们并再次运行剩余的组。我们需要最大化它们的交叉总和。
答案 0 :(得分:0)
可以直观地看到最佳解决方案。有3个最佳解决方案 2 + 6,2 + 7和3 + 8。
在算法上,最好的方法是使用强力方法。
从1开始(查看剩下的数字 - &gt; 4,5,6,7,8) 检查每个剩余的数字并记住每对的分数。
继续2(查看剩下的数字 - &gt; 6,7,8) 检查每个剩余的数字并记住每对的分数。
继续一直然后获得得分最高的一对。
请注意,您不需要检查已经检查过的对。 例如对于4,你不需要与1,2或3进行比较,因为它们之前已被检查过(1 + 4,2 + 4,3 + 4)。
答案 1 :(得分:0)
以免可视化您拥有的数据集:
======= (6,8)
============= (3,7)
============= (4,8)
============= (4,8)
========== (2,5)
======= (1,3)
--|--|--|--|--|--|--|--|--
1 2 3 4 5 6 7 8
Overlaps: 1 2 3 4 4 4 4 3
很明显假设间隔结束并且所有值都是整数有几个点,其中最大间隔重叠:4,5 ,6和7。
找到它们应该非常简单:
(pseudocode)
intervals=(
(6,8),
(3,7),
(4,8),
(4,8),
(2,5),
(1,3)
)
//Find the maximum point because it would be pointless to compute
//up to 10^9. You already know that the line starts at 1, otherwise
//you should find the minimum too.
lastPoint=1
for each interval
if interval(1)>lastPoint then
lastPoint=interval(1)
//Check each point
maxPoint=0
matchesAtMax=0
for i=1 to lastPoint
matches=0
for each interval
if interval(0)<=i and interval(1)>=i then
matches++
end for
if matches>=matchesAtMax then
maxPoint=i
matchesAtMax=matches
end if
end for
这将找到存储在maxPoint
的最后最高点,该点应该是7
样本数据。
现在,要再次运行它,我们应该以某种方式排除包含最大点的间隔,并仅检查剩余的间隔。我们可以在同一个循环中完成它。
(pseudocode)
intervals=(
(6,8),
(3,7),
(4,8),
(4,8),
(2,5),
(1,3)
)
//Find the maximum point because it would be pointless to compute
//up to 10^9. You already know that the line starts at 1, otherwise
//you should find the minimum too.
lastPoint=1
for each interval
if interval(1)>lastPoint then
lastPoint=interval(1)
//Check each point (the greatest first)
remainingIntervals=() //some kind of dynamic array
maxPoint2=0
matchesAtMax2=0 //Lets save both max matches so we can print the final sum
for i=1 to lastPoint
matches=0
remainingIntervalsTemp=()
for each interval
if interval(0)<=i and interval(1)>=i then
matches++
else
push interval into remainingIntervalsTemp
end if
end for
if matches>=matchesAtMax2 then
maxPoint2=i
matchesAtMax2=matches
remainingIntervals=remainingIntervalsTemp
end if
end for
//Check the points again using only the remaining intervals
//(Maybe update lastPoint first?)
maxPoint=0
matchesAtMax=0
for i=1 to lastPoint
matches=0
allMatchedAreRemaining=true
for each interval
if interval(0)<=i and interval(1)>=i then
//If this interval is not in the remaining, ignore the point
if interval is not in remainingIntervals then
allMatchedAreRemaining=false
exit for
end if
matches++
end if
end for
if allMatchedAreRemaining and matches>=matchesAtMax then
maxPoint=i
matchesAtMax=matches
end if
end for
print maxPoint "+" maxPoint2 "=" (matchesAtMax+matchesAtMax2)
答案将存储在maxPoint
和maxPoint2
。这应该打印2+7=6
样本数据。
优化它并使用函数是明智的,它只是一个想法,写得易于阅读,而不是完美运行。