给定两个包含范围[x1:x2]和[y1:y2],其中x1≤x2和y1≤y2,测试这两个范围是否有重叠的最有效方法是什么?

一个简单的实现如下:

bool testOverlap(int x1, int x2, int y1, int y2) {
  return (x1 >= y1 && x1 <= y2) ||
         (x2 >= y1 && x2 <= y2) ||
         (y1 >= x1 && y1 <= x2) ||
         (y2 >= x1 && y2 <= x2);
}

但是我希望有更有效的方法来计算这个。

就最少的操作而言,哪种方法是最有效的?


当前回答

从开始的最大值减去范围末端的最小值似乎可以达到目的。如果结果小于等于零,就有重叠。这很直观:

其他回答

你已经有了最有效的表示——这是需要检查的最小值,除非你确定x1 < x2等,然后使用其他人提供的解决方案。

你可能应该注意到,一些编译器实际上会为你优化它——只要这4个表达式中的任何一个返回true就返回。如果其中一个返回true,那么最终结果也会返回true——因此可以跳过其他检查。

西蒙的回答很好,但对我来说,相反的情况更容易思考。

什么时候两个范围不重叠?当其中一个开始后另一个结束时,它们不会重叠:

dont_overlap = x2 < y1 || x1 > y2

当它们重叠时,很容易表示:

overlap = !dont_overlap = !(x2 < y1 || x1 > y2) = (x2 >= y1 && x1 <= y2)

从开始的最大值减去范围末端的最小值似乎可以达到目的。如果结果小于等于零,就有重叠。这很直观:

值域重叠是什么意思?这意味着存在一个在两个范围内的数C,即。

x1 <= C <= x2

and

y1 <= C <= y2

为了避免混淆,考虑范围为: [x1:x2]和[y1:y2]

现在,如果我们可以假设范围是构造良好的(因此x1 <= x2和y1 <= y2),那么就足以进行测试

x1 <= y2 && y1 <= x2

OR

(StartA <= EndB)和(EndA >= StartB)

我相信min(upper(A),upper(B))>=max(lower(A),lower(B))将是一个很好的解决方案,不仅因为它的简单性,而且因为它超越了两个范围的可扩展性。