【问题标题】:Given a vector of intervals output any one number within the interval that has been overlapped the most times给定一个区间向量,输出区间内重叠次数最多的任意一个数字
【发布时间】:2015-05-28 02:47:53
【问题描述】:

假设我们这样定义区间

struct Interval {
  float start;
  float end;
  Interval() : start(0), end(0) {}
  Interval(float s, float e) : start(s), end(e) {}

};

如何输出重叠次数最多的区间内的任意一个数字?

例如,给定 [1.2,3.4],[2.6,6.8],[8.5,10.2],[15.1,18.7] 我们可以像 2.7 一样输出 [2.6, 3.4] 内的任何数字,因为 [2.6, 3.4] 是重叠次数最多(两次)的区间。

我的想法是按“开始”对间隔进行排序,然后在所有间隔中运行 for 循环。对于每个区间,我们计算后面的区间有多少个“开始”小于或等于其“结束”,并更新每个循环的最大值。

但这看起来像一个 O(n2) 的解决方案,我们可以做得更好吗?

【问题讨论】:

  • 如何在沿着范围移动时根据结束位置将结束间隔堆叠在优先级队列中,弹出最近的结束间隔或根据哪个最近的开始间隔推送下一个开始间隔,同时保持跑步“重叠”计数?
  • 如果您还有第二个按结束时间排序的间隔列表,则可以在 O(n log n) 时间内实现按开始时间对间隔进行排序的想法。

标签: c++ algorithm sorting


【解决方案1】:

这是一个简单的O(n log n) 解决方案,它使用事件和扫描线:

  1. 有两种类型的事件:间隔开始和间隔结束。

  2. 我们可以按坐标对所有事件进行排序(如果两个事件坐标相同,则对应区间开始的那个应该先走。如果它们是相同的类型,它们可以进入任何一个顺序)。

  3. 现在我们可以遍历间隔的排序数组,并在看到间隔开始时将 +1 添加到计数器,当看到结束时将 -1 添加到计数器。计数器的最大值就是答案。

  4. 为什么它是正确的?在任何时候,计数器的值都是从当前位置之前开始到之后结束的间隔数。这正是我们需要最大化的。

时间复杂度为O(n log n)(我们只需对事件数组进行排序,然后对其进行一次线性传递)。

【讨论】:

  • 并且您可以正确处理负间隔作为奖励。可爱。
  • 我不确定我是否正确理解了您的算法,但在示例中 [2.6, 3.4] 不是原始间隔之一吗?我们想要一个在这个范围内的数字,比如 2.7 或 3.1
  • @user3692521 问题陈述说我们可以从这个区间输出任何数字。很容易证明,在给定区间中至少有一个合适的区间总有一个终点。
  • 哦,我知道了,这很聪明!
猜你喜欢
  • 1970-01-01
  • 2022-01-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多