我可以使用除法和征服二分搜索来找到我想要的数字但是如何在不使用for循环和indexOf的情况下找到原始数组中的数字索引?
function search(array, value) {
var midpoint = Math.floor(array.length / 2)
if (value > array[midpoint]) {
var slicedArray = array.slice(midpoint)
} else {
var slicedArray = array.slice(0,midpoint)
}
return slicedArray[Math.floor((slicedArray.length/2))] === value ? value : search(slicedArray, value)
}
console.log(search([1,3,16,22,31,33,34], 34))
答案 0 :(得分:0)
您可以而且应该大量压缩此代码,但我已将其保留为更长的形式以更好地说明这些概念。
function search(array, value) {
if (array.length == 0)
return NaN;
var midpoint = Math.floor(array.length / 2);
if (array[midpoint] === value)
return midpoint;
if (array[midpoint] < value)
return search(array.slice(midpoint+1),value) + midpoint + 1;
if (array[midpoint] > value)
return search(array.slice(0,midpoint),value);
}
当你写一个递归函数时,你应该总是问自己的前两个问题是&#34;我怎么知道我已经完成了?&#34;并且&#34;不,真的,有没有办法达不到完成状态?&#34;
你想确定你已经涵盖了所有可能的状态。在这种情况下,有四个:
使用NaN
作为&#39;搜索失败&#39;返回值很方便,因为它避免了需要在检查条件逻辑的同时将递归值返回到链中; NaN
加上一个数字等于NaN
。
您不需要知道也不应该在找到原始数组时尝试计算搜索值的索引,稍后会进行几次递归调用。它是调用实例的工作,它将它知道的内容(它自己的中点)与递归的结果相结合,并返回一个有用的值来备份链。事实上,没有特别要求这个功能应该知道&#39;无论是原始电话还是递归。如果你发现自己需要知道这个问题的答案,那么你应该重新审视你的逻辑,这是一个警告标志。
答案 1 :(得分:0)
您可以使用包装函数_binarySearch
进行实际的二进制搜索,同时获取另外两个参数l, r
,而您可以使用两个参数调用搜索array, value
function _binarySearch(array, value, l, r) {
if (l > r) return -1;
var midPoint = Math.floor((l + r) / 2);
if (value == array[midPoint])
return midPoint;
else if (value > array[midPoint])
return _binarySearch(array, value, midPoint + 1, r);
else
return _binarySearch(array, value, l, midPoint - 1);
}
function search(array, value) {
return _binarySearch(array, value, 0, array.length);
}
如果你想知道元素的第一次出现,算法的最坏情况时间复杂度不再是 O(log n),它退化为 O(n)< /强>
这种修改是必要的
if (value == array[midPoint]) {
while(midPoint > -1 && array[midPoint] == value)
--midPoint;
return midPoint + 1;
}