Pulpcode

捕获,搅碎,拼接,吞咽

0%

判断区间是否'碰撞'

开始

之前的项目有这样一个需求,“在会议室申请时需要判断新的申请时间段是否与已存在的会议室申请时间段冲突”

这个问题的本质就是判断两个区间是否有交集
当然这里的区间与常见的编程区间不同,编程中讨论的区间是这样的:[begin, end)
而我要判断的是两个时间段是否冲突,所以我这里指的区间是闭区间:[begin, end]

实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
bool CollisionRange(Range this, Range other)
{
if(this.begin <= other.begin && other.begin <= this.end)
{
return true;
}

if(this.begin <= other.end && other.end <= this.end
{
return true;
}

return false;
}

后来发现这段代码是有bug的。他没能检查到other包含this的情况。
下面是新的方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
bool CollisionRange(Range this, Range other)
{
if(this.begin <= other.begin && other.begin <= this.end)
{
return true;
}
if(this.begin <= other.end && other.end <= this.end)
{
return true;
}
if(other.begin <= this.begin && other.end >= this.end)
{
return true;
}
return false;
}

更好的解决方案

后来我在《编写可读代码的艺术》中看见一种好的写法:

1
2
3
4
5
6
bool CollisionRange(Range this, Range other)
{
return (this.begin <= other.begin && other.begin <= this.end) ||
(this.begin <= other.end && other.end <= this.end) ||
(other.begin <= this.begin && other.end >= this.end);
}

不过这本书提供了一种更优雅的解决办法:
作者用一种逆向思维,从找不碰撞的方向出发。

1
2
3
4
5
6
7
bool CollisionRange(Range this, Range other)
{
if(this.end < other.begin) return false;
if(this.begin > other.end ) return false;

return true;
}

代码明显短了许多,清晰了许多。