Javascript 有效地查找某个数字范围内的对象
这是我的基本问题:我得到了一个Javascript 有效地查找某个数字范围内的对象,javascript,algorithm,loops,time,Javascript,Algorithm,Loops,Time,这是我的基本问题:我得到了一个currentTime。例如,750秒。我还有一个数组,其中包含1000到2000个对象,每个对象都有一个startTime,endTime,以及一个\u id属性。给定currentTime,我需要找到具有startTime和endTime的对象,该对象在该范围内——例如,startTime:740,endTime:755 在Javascript中最有效的方法是什么 首先,我只是做了一些类似的事情: var arrayLength = array.length;
currentTime
。例如,750秒。我还有一个数组,其中包含1000到2000个对象,每个对象都有一个startTime
,endTime
,以及一个\u id
属性。给定currentTime
,我需要找到具有startTime
和endTime
的对象,该对象在该范围内——例如,startTime:740
,endTime:755
在Javascript中最有效的方法是什么
首先,我只是做了一些类似的事情:
var arrayLength = array.length;
var x = 0;
while (x < arrayLength) {
if (currentTime >= array[x].startTime && currentTime <= array[x].endTime) {
// then I've found my object
}
x++;
};
听起来像是一个问题。假设您的搜索数组是长期存在且相对恒定的,第一次迭代将按开始时间对所有数组元素进行排序(或者创建一个已排序的开始时间索引,如果不希望排序,则指向数组元素) 然后,你可以有效地(用二进制印章)折扣那些开始太晚的。然后,依次搜索其他对象会更快 为了获得更高的速度,请为开始时间和结束时间维护单独的排序索引。然后执行前面提到的相同操作,以丢弃那些开始太晚的 然后,对于剩下的那些,使用结束时间索引扔掉那些结束得太早的,剩下的就是你的候选名单
但是,确保这是实际需要的。两千个元素看起来并不是一个很大的数量,所以你应该对当前的方法进行计时,只有在确实存在问题的情况下才尝试优化。根据给出的信息,不可能判断什么是最佳解决方案。如果数组未排序,循环是单个查询的最佳方式。沿数组的单次扫描只需要O(N)(其中N是数组的长度),而排序然后进行二进制搜索需要O(N log(N)+log(N)),因此在这种情况下需要更多的时间 如果在同一个大数组上有大量不同的查询,则分析结果将大不相同。如果在同一个数组上有大约N个查询,排序实际上可能会提高性能,因为每个查询都需要O(log(N))。因此,对于N个查询,它需要O(N log(N))(剩余的日志(N)现在被删除),而未排序的搜索也需要O(N^2),这显然更大。排序何时开始产生影响还取决于数组的大小 当您相当频繁地更新阵列时,情况也会有所不同。更新未排序的数组可以在O(1)摊销中完成,而更新排序的数组需要O(N)。因此,如果您有相当频繁的更新,排序可能会造成伤害
对于范围查询,也有一些非常有效的数据结构,但是,如果它们有意义与否,则取决于实际使用情况 解决此问题的最佳方法取决于调用搜索函数的次数 如果只调用函数几次,比如说
m次
,那么就进行线性搜索。此函数调用的总体复杂性为O(mn)
如果多次调用函数,我所说的多次是指超过log(n)
次,您应该:
- 如果有多个项目的
startTime
- 使用
startTime查找元素范围如果数组未排序,则您的方法是正确的 不要陷入先对数组排序,然后应用搜索的思维陷阱 对于您尝试的代码,您的复杂性为O(n),其中n是元素的数量 如果首先对数组进行排序,则在
平均情况下,首先会陷入复杂性O(n log(n))(与之相比) 然后,您必须应用二进制搜索,它以O(log_2(n)-1)的平均复杂度执行 因此,在一般情况下,你最终会花费: O(n日志(n)+(日志2(n)-1)) An是一种数据结构,它不只是O(n)An,而是允许在O(lg n)时间内(平均和最坏情况下)回答此类查询,前提是总共有n个间隔。构造数据结构的预处理时间为O(nlgn);空间是O(n)。对于间隔树,插入和删除时间为O(lgn)。如果m个区间覆盖一个点,则回答所有区间查询的时间为O(m+lgn)。描述了几种区间树;例如,居中间隔树是三级树,每个节点存储: •中心点
•指向另一个节点的指针,该节点包含完全位于中心点左侧的所有间隔
•指向另一个节点的指针,该节点包含完全位于中心点右侧的所有间隔
•所有重叠中心点的间隔,按其起点排序
•所有重叠中心点的间隔,按其终点排序 注意,对于找到一个区间覆盖一个点的平均和最坏情况查询,区间树的复杂度都是O(lgn)。对于相同的问题,前面的答案的最坏情况查询性能为O(n)。之前的几个答案声称它们的平均时间为O(lgn)。但他们都没有提供证据;相反,他们只是断言平均性能为O(lgn)。前面这些答案的主要特点是使用二进制搜索开始时间。然后一些人说使用线性搜索,另一些人说使用二进制搜索,用于结束时间,但没有明确后一种搜索结束的时间间隔集。他们声称拥有O(lgn)的平均性能,但这只是一厢情愿。正如维基百科文章所指出的var binarySearch = function(array, currentTime) { var low = 0; var high = array.length - 1; var i; while (low <= high) { i = Math.floor((low + high) / 2); if (array[i].startTime <= currentTime) { if (array[i].endTime >= currentTime ){ // this is the one return array[i]._id; } else { low = i + 1; } } else { high = i - 1; } } return null; }