找到两个区间交集的最简单方法

计算科学 算法 区间算术
2021-11-23 22:05:10

现在我遇到了一个问题。这似乎真的很微不足道,但我仍然很难找到合适的解决方案。问题是:一个有两个区间,要找到它们的交集。

例如:

  • [0, 3]&[2, 4]的交集[2, 3]
  • [-1, 34]&[0, 4]的交集[0, 4]
  • [0, 3]&[4, 4]的交集空集

很明显,可以通过对所有可能的情况进行测试来解决问题,但是这会花费很多时间并且很容易出错。有没有更简单的方法来解决这个问题?如果您知道解决方案,请帮助我。将不胜感激。

4个回答

我们可以通过以下方式定义此问题的解决方案。假设输入间隔可以定义为Ia=[as,ae]Ib=[bs,be],而输出区间定义为Io=[os,oe]. 我们可以找到交叉点Io=IaIb执行以下操作:

如果(bs>ae或者as>be) { 返回 }

否则{

os=max(as,bs)

oe=min(ae,be)

返回 [os,oe]

}

ahmednabil88的回答是正确的。让我根据简单的布尔代数给你一个解释。为了自给自足,我们在这里重申问题:

给定两个闭合区间 [start1, end1], [start2, end2],我们想要一个最小的布尔表达式,它是真当且当。两个区间重叠。

很难枚举所有相交的情况。但只有两种情况下两个区间不重叠。不重叠的布尔表达式是:

(start1end1<start2end2)(start2end2<start1end1)

我们简单地取否定来得到重叠的表达式:

¬((start1end1<start2end2)(start2end2<start1end1))

但是,如果我们手动简化表达式,实现会更有效率。我们先重写表达式:

¬((start1end1end1<start2start2end2)(start2end2end2<start1start1end1))

注意可以被杀死,因为它们已经被假定为真。所以我们有:start1end1start2end2

¬((end1<start2)(end2<start1))

根据德摩根的规则,我们有:

¬(end1<start2)¬(end2<start1)

再次根据 De Morgan 的规则,我们得出结论:

end1start2end2start1

假设我们只有两个输入区间。

  1. 确保第一个区间的开始时间<第二个区间的开始时间。
  2. 重叠意味着一个区间的结束时间在另一个区间的开始时间之后
public int[] overlap(int[] i1, int[] i2) {
    // Make sure the start time of first interval < the start time of second interval.
    if(i1.startTime > i2.startTime) {
        return overlap(i2, i1);
    }

    // Overlap means an interval's end time is after another interval's start time
    if(i1.endTime > i2.startTime) {
        return new Interval(i2.startTime, Math.min(i1.endTime, i2.endTime));
    }
    else {
        return null;
    }
}
  • 时间复杂度:O(1)
  • 空间复杂度:O(1)

另一种简单的方式

给定:
2 个区间
区间 1 : (start1, end1)
区间 2 : (start2, end2)

必需:
用于检查两个区间是否相交的布尔条件

解决方案:考虑到 2 个区间相交,
以下两个条件
应为真: 1. end2 >= start1
2. start2 <= end1

// check 2 intervals are intersected or not
if( (end2 >= start1) && (start2 <= end1) ){
    // 2 intervals are intersected
    // ...

}else{
    // 2 intervals are NOT intersected
    // ...

}