这是情况。我有一个整数的排序列表,表示需要在某个毫秒内触发的事件。该列表可能如下所示:
0
1500
5000
9348
89234
109280
109281
109283
150000
然后我有一个playhead
通常每100毫秒向前移动一次,但也可以随机搜索并向前和向后擦洗。该播放头不能保证是100的倍数,但可以在没有任何实际问题的情况下被覆盖到该倍数。
我的挑战是能够有效地在列表中找到小于或等于当前播放头的最接近元素。列表的平均长度在300到1500个元素之间。我可以相当容易地以设定的间隔优化前进,但随机搜索稍微复杂一些。
让我希望我不会在算法课上睡觉。
答案 0 :(得分:1)
我认为Divide and conquer algorithm是最适合的。
答案 1 :(得分:1)
听起来你想要修改二进制搜索。由于列表是按排序顺序排列的,因此二进制搜索将大大提高线性搜索的搜索性能,如果您对阵列中项目的间距一无所知,则不能做得比二进制搜索。二进制搜索需要稍加修改,因为你不是在寻找相等的东西,而是在没有经过的情况下尽可能接近。
这是一个实际的算法,它将搜索数据分成1/2(每次基于与测试值的比较,与上半部分或下半部分一起),直到它只变为一个要素:
var testData = [0,1500,5000,9348,89234,109280,109281,109283,150000];
function findNearest(data, val) {
if (!data || !data.length) {
return(null);
}
var lowest = 0, mid;
var highest = data.length - 1;
while (true) {
if (lowest == highest) {
return(lowest);
}
mid = Math.ceil(((highest - lowest) / 2) + lowest);
if (data[mid] == val) {
return(mid);
}
else if (data[mid] < val) {
lowest = mid;
} else {
highest = Math.max(lowest, mid - 1);
}
}
}
并且,一个有效的测试程序:http://jsfiddle.net/jfriend00/rWk2X/
注意:此代码假定数组中的所有值都按排序顺序排列,并且数组不为空。
如果给它一个没有小于目标值的数组,它将返回0,这可能是你需要处理的特殊情况,除非确定数组中的第一个值总是小于目标值(例如总是零)。
如果你给它一个没有大于目标值的数组,它将返回数组中的最后一个值(应该如此),这不是一个特例,只是想要的答案。
答案 2 :(得分:0)
由于它是一个排序列表,因此请使用二进制搜索。你可以做得更好,但是你必须做出额外的假设(例如,你必须假设数字的均匀分布,我不认为是这种情况)。您可以在此处阅读:http://en.wikipedia.org/wiki/Binary_search_algorithm
答案 3 :(得分:0)