找到最大交点间隔发生2次的点

时间:2018-05-05 16:14:37

标签: algorithm data-structures

我最近参加了一个离线竞赛,他们问了这个问题。

给定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个点,使得每个区间中的交点总和最大。就像您首先这样做,找到一组相交的范围,然后删除它们并再次运行剩余的组。我们需要最大化它们的交叉总和。

2 个答案:

答案 0 :(得分:0)

可以直观地看到最佳解决方案。有3个最佳解决方案 2 + 6,2 + 7和3 + 8。

enter image description here

在算法上,最好的方法是使用强力方法。

从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)

答案将存储在maxPointmaxPoint2。这应该打印2+7=6样本数据。

优化它并使用函数是明智的,它只是一个想法,写得易于阅读,而不是完美运行。