假设我们有一些间隔
const INTERVALS = [
['14:00', '15:00'],
['08:00', '12:30'],
['12:35', '12:36'],
['13:35', '13:50'],
];
如果我们想在这个列表中添加新的区间,我们应该检查新的区间是否与其中的一些重叠。
您可以循环波谷间隔并检查新的间隔是否与其他间隔重叠。请注意,在比较时间间隔时,如果您确定它与可以将时间转换为数字的日期相同,则不需要 Date 对象:
function convertTimeToNumber(time) {
const hours = Number(time.split(':')[0]);
const minutes = Number(time.split(':')[1]) / 60;
return hours + minutes;
}
间隔不重叠的情况有两种:
- 在 (a
a b
|----------|
c d
|----------|
- 在 where (a > c && a > d) && (b > c && b > d) 之后:
a b
|----------|
c d
|----------|
因为总是c < d,所以说不重叠区间的条件是(a < c && b < c) || (a > d && b > d)就足够了,因为总是a < b,所以说这个条件相当于:
b < c || a > d
否定这个条件应该给我们一个重叠间隔的条件。基于De Morgan's laws 是:
b >= c && a <= d
请注意,在这两种情况下,间隔不能相互“接触”,这意味着 5:00-8:00 和 8:00-9:00 将重叠。如果你想允许它,条件应该是:
b > c && a < d
至少有5种重叠区间的情况需要考虑:
a b
|----------|
c d
|----------|
a b
|----------|
c d
|----------|
a b
|----------|
c d
|--------------------|
a b
|--------------------|
c d
|----------|
a b
|----------|
c d
|----------|
带有额外添加和排序间隔函数的完整代码如下:
const INTERVALS = [
['14:00', '15:00'],
['08:00', '12:30'],
['12:35', '12:36'],
['13:35', '13:50'],
];
function convertTimeToNumber(time) {
const hours = Number(time.split(':')[0]);
const minutes = Number(time.split(':')[1]) / 60;
return hours + minutes;
}
// assuming current intervals do not overlap
function sortIntervals(intervals) {
return intervals.sort((intA, intB) => {
const startA = convertTimeToNumber(intA[0]);
const endA = convertTimeToNumber(intA[1]);
const startB = convertTimeToNumber(intB[0]);
const endB = convertTimeToNumber(intB[1]);
if (startA > endB) {
return 1
}
if (startB > endA) {
return -1
}
return 0;
})
}
function isOverlapping(intervals, newInterval) {
const a = convertTimeToNumber(newInterval[0]);
const b = convertTimeToNumber(newInterval[1]);
for (const interval of intervals) {
const c = convertTimeToNumber(interval[0]);
const d = convertTimeToNumber(interval[1]);
if (a < d && b > c) {
console.log('This one overlap: ', newInterval);
console.log('with interval: ', interval);
console.log('----');
return true;
}
}
return false;
}
function isGoodInterval(interval) {
let good = false;
if (interval.length === 2) {
// If you want you can also do extra check if this is the same day
const start = convertTimeToNumber(interval[0]);
const end = convertTimeToNumber(interval[1]);
if (start < end) {
good = true;
}
}
return good;
}
function addInterval(interval) {
if (!isGoodInterval(interval)) {
console.log('This is not an interval');
return;
}
if (!isOverlapping(INTERVALS, interval)) {
INTERVALS.push(interval);
// you may also want to keep those intervals sorted
const sortedIntervals = sortIntervals(INTERVALS);
console.log('Sorted intervals', sortedIntervals);
}
}
// --------------------------------------
const goodIntervals = [
['05:31', '06:32'],
['16:00', '17:00'],
['12:31', '12:34']
];
let goodCount = 0;
for (const goodInterval of goodIntervals) {
if (!isOverlapping(INTERVALS, goodInterval)) {
goodCount += 1
}
}
console.log('Check good intervals: ', goodCount === goodIntervals.length);
// --------------------------------------
const ovelappingIntervals = [
['09:30', '12:40'],
['05:36', '08:50'],
['13:36', '13:37'],
['06:00', '20:00'],
['14:00', '15:00']
]
let badCount = 0;
for (const badInterval of ovelappingIntervals) {
if (isOverlapping(INTERVALS, badInterval)) {
badCount += 1
}
}
console.log('Check bad intervals: ', badCount === ovelappingIntervals.length);
// --------------------------------------
addInterval(goodIntervals[0])