给定两个包含范围[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],则[y1, y2]应在[x1, x2]之外,即y1 < y2 < x1或x2 < y1 < y2,这等价于y2 < x1或x2 < y1。

因此,使两个范围重叠的条件是:不(y2 < x1或x2 < y1),这相当于y2 >= x1和x2 >= y1(与Simon接受的答案相同)。

其他回答

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

如果有人正在寻找计算实际重叠的一行程序:

int overlap = ( x2 > y1 || y2 < x1 ) ? 0 : (y2 >= y1 && x2 <= y1 ? y1 : y2) - ( x2 <= x1 && y2 >= x1 ? x1 : x2) + 1; //max 11 operations

如果你想要少一些操作,但多一些变量:

bool b1 = x2 <= y1;
bool b2 = y2 >= x1;
int overlap = ( !b1 || !b2 ) ? 0 : (y2 >= y1 && b1 ? y1 : y2) - ( x2 <= x1 && b2 ? x1 : x2) + 1; // max 9 operations

我的情况不同。我要检查两个时间范围是否重叠。不应该有单位时间的重叠。这里是Go的实现。

    func CheckRange(as, ae, bs, be int) bool {
    return (as >= be) != (ae > bs)
    }

测试用例

if CheckRange(2, 8, 2, 4) != true {
        t.Error("Expected 2,8,2,4 to equal TRUE")
    }

    if CheckRange(2, 8, 2, 4) != true {
        t.Error("Expected 2,8,2,4 to equal TRUE")
    }

    if CheckRange(2, 8, 6, 9) != true {
        t.Error("Expected 2,8,6,9 to equal TRUE")
    }

    if CheckRange(2, 8, 8, 9) != false {
        t.Error("Expected 2,8,8,9 to equal FALSE")
    }

    if CheckRange(2, 8, 4, 6) != true {
        t.Error("Expected 2,8,4,6 to equal TRUE")
    }

    if CheckRange(2, 8, 1, 9) != true {
        t.Error("Expected 2,8,1,9 to equal TRUE")
    }

    if CheckRange(4, 8, 1, 3) != false {
        t.Error("Expected 4,8,1,3 to equal FALSE")
    }

    if CheckRange(4, 8, 1, 4) != false {
        t.Error("Expected 4,8,1,4 to equal FALSE")
    }

    if CheckRange(2, 5, 6, 9) != false {
        t.Error("Expected 2,5,6,9 to equal FALSE")
    }

    if CheckRange(2, 5, 5, 9) != false {
        t.Error("Expected 2,5,5,9 to equal FALSE")
    }

你可以在边界比较中看到异或模式

给定两个范围[x1,x2], [y1,y2]

def is_overlapping(x1,x2,y1,y2):
    return max(x1,y1) <= min(x2,y2)

反过来思考:如何使这两个范围不重叠?给定[x1, x2],则[y1, y2]应在[x1, x2]之外,即y1 < y2 < x1或x2 < y1 < y2,这等价于y2 < x1或x2 < y1。

因此,使两个范围重叠的条件是:不(y2 < x1或x2 < y1),这相当于y2 >= x1和x2 >= y1(与Simon接受的答案相同)。