我目前有一个这样的数组:
[1,1,2,3,4,5,5,5,6,7,8,8,8,8,9,10]
我一直在使用来自this website的优秀JS二进制搜索公式:
searchArray = function(needle, haystack, case_insensitive) {
if (typeof(haystack) === 'undefined' || !haystack.length) return -1;
var high = haystack.length - 1;
var low = 0;
case_insensitive = (typeof(case_insensitive) === 'undefined' || case_insensitive) ? true:false;
needle = (case_insensitive) ? needle.toLowerCase():needle;
while (low <= high) {
mid = parseInt((low + high) / 2)
element = (case_insensitive) ? haystack[mid].toLowerCase():haystack[mid];
if (element > needle) {
high = mid - 1;
} else if (element < needle) {
low = mid + 1;
} else {
return mid;
}
}
return -1;
};
这适用于返回单个值。
如何返回范围而不是单个值?例如,我如何从数组中返回8
的所有值,但是STILL使用二进制搜索(我不想遍历所有内容!!)。
谢谢!
答案 0 :(得分:3)
这样的东西? http://jsfiddle.net/DCLey/3/
var arr = ['1','1','2','3','4','5','5','5','6','7','8','8','8','8','9','10'];
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
var searchArray = function(needle, haystack, case_insensitive) {
if (typeof(haystack) === 'undefined' || !haystack.length) return -1;
var high = haystack.length - 1;
var low = 0;
var vals = [];
var bUp = true;
var bDown = true;
var i = 1;
case_insensitive = (typeof(case_insensitive) === 'undefined' || case_insensitive) ? true:false;
needle = (case_insensitive) ? needle.toLowerCase():needle;
while (low <= high) {
mid = parseInt((low + high) / 2)
element = (case_insensitive) ? haystack[mid].toLowerCase():haystack[mid];
if (element > needle) {
high = mid - 1;
} else if (element < needle) {
low = mid + 1;
} else {
vals.push(mid);
while(bUp || bDown){
if(bUp && haystack[mid] === haystack[mid + i]){
vals.push(mid + i);
}else{
bUp = false;
}
if(bDown && haystack[mid] === haystack[mid - i]){
vals.push(mid - i);
}else{
bDown = false;
}
i++;
}
return vals;
}
}
return -1;
};
alert(searchArray('8', arr, true));
答案 1 :(得分:0)
除非您只想计算给定数字的实例数,否则您需要返回数组中数字的上下索引。我们可以从两种方法中选择:
采用方法2的性能稍差,但保留了一般算法。