【发布时间】:2021-06-21 16:10:59
【问题描述】:
我有一个日志项数组,已按其时间戳(自 1970 年以来的毫秒数)排序。现在我想按特定时间范围过滤它们,所以我想到了二进制搜索,但是这个变体与我之前知道的所有变体不同,因为我需要在一个范围内找到一个范围。请注意,值边缘可能没有或有多个项目。
我想出了这个来减少一个范围要求,但仍然不知道如何到达第一个/最后一个边缘项目:
filterByTime(min: number, max: number): LogItem[] {
const items = this.items;
const len = items.length;
if (min === undefined && max === undefined) {
return items.slice(0, len - 1);
}
min = min || Number.MIN_VALUE;
max = max || Number.MAX_VALUE;
const fn = (a: LogItem) => {
if (a.time < min) {
return -1;
} else if (a.time > max) {
return 1;
} else {
return 0;
}
};
const lowerBound = this.binarySearchBound(fn, 0, len, true);
if (lowerBound == -1) { return []; }
const upperBound = this.binarySearchBound(fn, 0, len, false);
return items.slice(lowerBound, upperBound + 1);
}
binarySearchBound(compareFn: (a: LogItem) => number, left: number, right: number, isLowerBound: boolean): number {
const items = this.items;
if (items.length == 0) {
return -1;
}
if (isLowerBound && compareFn(items[0]) == 0) {
return 0;
} else if (!isLowerBound && compareFn(items[items.length - 1]) == 0) {
return items.length - 1;
}
while (left <= right) {
const mid = (left + right) / 2;
const item = this.items[mid];
const compare = compareFn(item);
if (compare < 0) {
left = mid + 1;
} else if (compare > 0) {
right = mid - 1;
} else {
// What to do now?
}
}
return -1;
}
最坏的情况,我可以从边缘进行线性搜索,因为我可以假设边缘没有那么多项,但肯定有更好的方法我没有想到但是如果 mid 位于结果集的中间,我可能不得不遍历整个结果集。
添加注释的编辑:min 或 max 可能是 undefined(也可以是两者,在这种情况下,我可以设置一个 if 并返回整个数组的副本)。如果 MIN_VALUE 和 MAX_VALUE 是 undefined,则将其替换为更好,还是有更好的方法来处理这种情况?
【问题讨论】:
标签: javascript typescript algorithm binary-search